{"record":{"id":"56d250e09cf8eb63","repo":"affaan-m/ECC","slug":"refusing-unverified-ownership-from-install-state-a-56d250","errorCode":null,"errorMessage":"Refusing unverified ownership from install-state at ${plan.installStatePath}: content digest does not match ${destinationPath}.","messagePattern":"Refusing unverified ownership from install-state at (.+?): content digest does not match (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/multi-harness-setup.js","lineNumber":178,"sourceCode":"    }\n    const destinationPath = operation.destinationPath;\n    assertWithinTrustedRoot(destinationPath, plan.targetRoot, 'trust install-state ownership');\n    const canonicalDestination = canonicalPath(destinationPath);\n    const plannedOperation = plannedByDestination.get(canonicalDestination);\n    if (!plannedOperation) continue;\n    if (!operationIdentityMatches(operation, plannedOperation)) {\n      throw new Error(\n        `Refusing unverified ownership from install-state at ${plan.installStatePath}: `\n        + `operation identity does not match the current plan for ${destinationPath}.`\n      );\n    }\n    const currentFingerprint = fingerprintFile(destinationPath);\n    if (\n      !currentFingerprint.exists\n      || !/^[a-f0-9]{64}$/i.test(operation.contentSha256 || '')\n      || currentFingerprint.sha256 !== operation.contentSha256.toLowerCase()\n    ) {\n      throw new Error(\n        `Refusing unverified ownership from install-state at ${plan.installStatePath}: `\n        + `content digest does not match ${destinationPath}.`\n      );\n    }\n    destinations.add(canonicalDestination);\n  }\n  return { destinations, stateFingerprint: validatedFingerprint };\n}\n\nfunction assertMergeDestination(destinationPath) {\n  if (!fs.existsSync(destinationPath)) return null;\n  let current;\n  try {\n    current = JSON.parse(fs.readFileSync(destinationPath, 'utf8'));\n  } catch (error) {\n    throw new Error(`Cannot merge ECC configuration into invalid JSON at ${destinationPath}: ${error.message}`);\n  }\n  if (!current || typeof current !== 'object' || Array.isArray(current)) {","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/multi-harness-setup.js#L160-L196","documentation":"Thrown by readOwnedDestinations after the identity check passes, when the destination file's current SHA-256 does not match the operation's recorded contentSha256. This is the cryptographic proof that ECC still owns the file: even if identity matches, if the bytes on disk differ from what ECC wrote (or the file is missing, or contentSha256 is malformed), ownership is no longer verifiable and the file is treated as user-modified. The regex /^[a-f0-9]{64}$/i also rejects malformed or missing digests.","triggerScenarios":"Fires when fingerprintFile(destinationPath).exists is false, when operation.contentSha256 is not a valid 64-char hex digest, or when the current sha256 differs from contentSha256.toLowerCase(). Occurs when the user edited an ECC-managed file, another tool rewrote it (formatter, postinstall), the file was deleted, or the state's contentSha256 field was corrupted/uppercased/truncated.","commonSituations":"User hand-editing an ECC-managed config file; a linter/formatter rewriting a managed file on save; partial checkout where the file is missing; git line-ending normalization changing the digest; state corruption altering contentSha256; cross-platform EOL differences changing the hash.","solutions":["If you intentionally modified the file, remove the install-state and re-run the preview so ECC re-records ownership of the current bytes (or move your edits aside first).","Restore the file to the exact bytes ECC wrote (e.g., git checkout the managed version) so the digest matches contentSha256.","If contentSha256 in the state looks malformed, treat the state as corrupt: delete it and regenerate.","Disable formatters/linters that rewrite ECC-managed files, or add them to the managed set explicitly."],"exampleFix":"// before: user edited managed file, digest no longer matches state\n// state op.contentSha256 = 'aa...'\n// current file sha256      = 'bb...'\nreadOwnedDestinations(plan); // throws [288]\n\n// after (option A): re-record ownership for the edited file\nfs.rmSync(plan.installStatePath, { force: true });\nconst plan2 = await createMultiHarnessPlan(req);\nawait applyMultiHarnessPlan(plan2);\n\n// after (option B): restore original bytes\nfs.copyFileSync(originalManagedFile, destinationPath);","handlingStrategy":"validation","validationCode":"const fs = require('fs'); const crypto = require('crypto');\nfunction assertDestinationsMatchDigests(statePath) {\n  if (!fs.existsSync(statePath)) return;\n  const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));\n  for (const op of state.operations || []) {\n    if (!fs.existsSync(op.destinationPath)) {\n      throw new Error(`Managed file missing: ${op.destinationPath}`);\n    }\n    if (!/^[a-f0-9]{64}$/i.test(op.contentSha256 || '')) {\n      throw new Error(`Malformed contentSha256 for ${op.destinationPath}`);\n    }\n    const cur = crypto.createHash('sha256').update(fs.readFileSync(op.destinationPath)).digest('hex');\n    if (cur !== op.contentSha256.toLowerCase()) {\n      throw new Error(`Managed file modified externally: ${op.destinationPath}`);\n    }\n  }\n}\nassertDestinationsMatchDigests(plan.installStatePath);","typeGuard":"null","tryCatchPattern":"try {\n  await applyMultiHarnessPlan(plan);\n} catch (err) {\n  if (/content digest does not match/.test(err.message)) {\n    // decide: re-record ownership (delete state + re-preview) or restore the original bytes\n    fs.rmSync(plan.installStatePath, { force: true });\n    const fresh = await createMultiHarnessPlan(plan.request);\n    await applyMultiHarnessPlan(fresh);\n  } else throw err;\n}","preventionTips":["Do not hand-edit ECC-managed files; if you must, delete the install-state and re-install.","Disable formatters/linters that auto-rewrite managed config files.","Normalize line endings project-wide so cross-platform checkout does not change digests.","Treat unexpected digest drift as a signal the file was modified, not as an ECC bug."],"tags":["install-state","content-digest","sha256","ownership","tamper-detection","kimi"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}