{"record":{"id":"b506412ca605144e","repo":"ruvnet/RuView","slug":"reporoot-and-trustedroot-are-required","errorCode":null,"errorMessage":"repoRoot and trustedRoot are required","messagePattern":"repoRoot and trustedRoot are required","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"harness/homecore/src/repo-trust.js","lineNumber":64,"sourceCode":"export function looksLikeHomecoreRepo(path) {\n  if (!path || !existsSync(path)) return false;\n  return REQUIRED_MARKERS.every((marker) => existsSync(join(path, marker)));\n}\n\nexport function findHomecoreRepo(start = process.cwd()) {\n  let current = resolve(start);\n  const root = parse(current).root;\n  while (true) {\n    if (looksLikeHomecoreRepo(current)) return realpathSync(current);\n    if (current === root) return null;\n    const parent = dirname(current);\n    if (parent === current) return null;\n    current = parent;\n  }\n}\n\nexport function assertTrustedHomecoreRepo(repoRoot, { trustedRoot = repoRoot } = {}) {\n  if (!repoRoot || !trustedRoot) throw new TypeError('repoRoot and trustedRoot are required');\n  const root = realpathSync(repoRoot);\n  const trustAnchor = realpathSync(trustedRoot);\n  if (!isWithin(trustAnchor, root) || root !== trustAnchor) {\n    throw new Error('Refusing CLI access: repository does not match the configured trusted root');\n  }\n  if (!statSync(root).isDirectory()) {\n    throw new Error('Refusing CLI access: trusted root is not a directory');\n  }\n  const missing = REQUIRED_MARKERS.filter((marker) => !existsSync(join(root, marker)));\n  if (missing.length) {\n    throw new Error(`Refusing CLI access: Homecore repository markers are missing (${missing.join(', ')})`);\n  }\n  const readme = readContainedPrefix(root, join(root, 'README.md'), 131_072);\n  if (!/\\b(?:RuView|wifi[- ]densepose)\\b/i.test(readme)) {\n    throw new Error('Refusing CLI access: README does not identify a RuView checkout');\n  }\n  return root;\n}","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/ruvnet/RuView/blob/4685618388a5e49fad5b3005806f3bdd6a7c25c3/harness/homecore/src/repo-trust.js#L46-L82","documentation":"assertTrustedHomecoreRepo() requires both repoRoot and trustedRoot to be non-empty. trustedRoot defaults to repoRoot, but explicitly passing '' or null in the options object overrides that default, so both parameters end up checked and this TypeError is thrown.","triggerScenarios":"assertTrustedHomecoreRepo(''), assertTrustedHomecoreRepo(null), or assertTrustedHomecoreRepo(root, {trustedRoot: ''}) — typically an unvalidated --repo flag or an env variable that resolves to an empty string.","commonSituations":"Env-based config like process.env.HOMECORE_TRUSTED_ROOT ?? '' normalizing unset to empty string, CLI wrappers forwarding missing arguments verbatim.","solutions":["Pass non-empty absolute path strings for both parameters","Normalize empty strings to undefined before calling so the default applies","Validate CLI/env input before forwarding it to this function"],"exampleFix":"// before\nassertTrustedHomecoreRepo(args.repo, { trustedRoot: env.HOMECORE_TRUSTED_ROOT ?? '' });\n\n// after\nconst trusted = env.HOMECORE_TRUSTED_ROOT || args.repo;\nassertTrustedHomecoreRepo(args.repo, { trustedRoot: trusted });","handlingStrategy":"type-guard","validationCode":"const hasTrustRoots = (repoRoot, opts = {}) =>\n  Boolean(repoRoot) && Boolean(opts.trustedRoot ?? repoRoot);\nif (!hasTrustRoots(args.repo, opts)) throw new TypeError('repoRoot and trustedRoot are required');","typeGuard":"/** @param {unknown} v @returns {v is string} */\nfunction isNonEmptyPath(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Convert empty-string env/CLI values to undefined before passing them as trustedRoot so the default applies","Resolve paths once at startup and pass the resolved values everywhere","Validate required path arguments at the CLI boundary, not deep in trust verification"],"tags":["validation","typeerror","cli","homecore"],"backgroundTag":null,"analyzedSha":"4685618388a5e49fad5b3005806f3bdd6a7c25c3","analyzedAt":"2026-08-16T06:09:40.886Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}