{"record":{"id":"6c6a60bd9542d202","repo":"ruvnet/ruflo","slug":"auditreadview-must-be-an-object","errorCode":null,"errorMessage":"auditReadView must be an object","messagePattern":"auditReadView must be an object","errorType":"validation","errorClass":"PodTemplateValidationError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/business-pods/pod-schema.ts","lineNumber":158,"sourceCode":"  const successCriteria = requireArray(item, 'successCriteria', path, (s, sp) => {\n    if (typeof s !== 'string' || s.length === 0) {\n      throw new PodTemplateValidationError('successCriteria entries must be non-empty strings', sp);\n    }\n    return s;\n  });\n  if (successCriteria.length === 0) {\n    throw new PodTemplateValidationError('bench.successCriteria must have ≥1 entry', path);\n  }\n  const scheduleHours = requireNumber(item, 'scheduleHours', path);\n  if (scheduleHours < 1) {\n    throw new PodTemplateValidationError('bench.scheduleHours must be ≥1', path);\n  }\n  return { name, description, successCriteria, scheduleHours };\n}\n\nfunction validateAuditReadView(item: unknown, path: string): PodAuditReadView {\n  if (!isObject(item)) {\n    throw new PodTemplateValidationError('auditReadView must be an object', path);\n  }\n  const includedEventTypes = requireArray(item, 'includedEventTypes', path, (s, sp) => {\n    if (typeof s !== 'string' || s.length === 0) {\n      throw new PodTemplateValidationError('includedEventTypes entries must be non-empty strings', sp);\n    }\n    return s;\n  });\n  const retentionDays = requireNumber(item, 'retentionDays', path);\n  if (retentionDays < 1) {\n    throw new PodTemplateValidationError('auditReadView.retentionDays must be ≥1', path);\n  }\n  return { includedEventTypes, retentionDays };\n}\n\n// POSIX cron — five or six space-separated fields. Permissive on field\n// contents (digits, *, -, /, ,) — actual cron evaluation happens at schedule\n// time. We only catch obviously malformed values here.\nconst CRON_RE = /^([\\d*/,\\-]+\\s+){4,5}[\\d*/,\\-]+$/;","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/business-pods/pod-schema.ts#L140-L176","documentation":"Thrown by validateAuditReadView() when json.auditReadView fails the isObject() check. The audit read-view (which event types an auditor can see and for how long) must be a plain JSON object with includedEventTypes and retentionDays — null, arrays, strings, and numbers are all rejected, and omission yields undefined which also fails isObject().","triggerScenarios":"A pod template where auditReadView is missing entirely, set to null, an array (e.g. a bare list of event types), or a string like \"all\". Path reported is /auditReadView.","commonSituations":"Authors inlining the event-type list directly under auditReadView instead of nesting it under includedEventTypes, or scaffolding templates with a null placeholder that was never filled in.","solutions":["Provide auditReadView as an object: { \"includedEventTypes\": [\"...\"], \"retentionDays\": 90 }","If you meant 'no audit view', note the schema does not allow omitting it — pick a minimal retention and event list","Validate again via business_pod_validate to confirm the next field-level errors (if any) surface"],"exampleFix":"// before\n\"auditReadView\": [\"pod.started\", \"pod.completed\"]\n// after\n\"auditReadView\": { \"includedEventTypes\": [\"pod.started\", \"pod.completed\"], \"retentionDays\": 90 }","handlingStrategy":"validation","validationCode":"const av = (JSON.parse(raw) as Record<string, unknown>).auditReadView;\nconst ok = typeof av === 'object' && av !== null && !Array.isArray(av);\nif (!ok) throw new Error('auditReadView must be an object with includedEventTypes and retentionDays');","typeGuard":"function isAuditReadViewLike(v: unknown): v is { includedEventTypes: unknown; retentionDays: unknown } {\n  return typeof v === 'object' && v !== null && !Array.isArray(v)\n    && 'includedEventTypes' in v && 'retentionDays' in v;\n}","tryCatchPattern":"try { validatePodTemplate(json); } catch (err) {\n  if (err instanceof PodTemplateValidationError && err.path === '/auditReadView') {\n    // rewrite auditReadView as { includedEventTypes: [...], retentionDays: N }\n  }\n}","preventionTips":["Use the exported PodAuditReadView-equivalent shape as a TS type in template generators","Never inline the event list directly under auditReadView"],"tags":["schema-validation","business-pods","audit","configuration"],"backgroundTag":"schema-validation-failed","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}