{"record":{"id":"012ffc0f4f4fd8fc","repo":"paperclipai/paperclip","slug":"cheap-status-only-recovery-runs-cannot-update-issu","errorCode":null,"errorMessage":"Cheap status-only recovery runs cannot update issue documents, plans, or deliverable artifacts","messagePattern":"Cheap status-only recovery runs cannot update issue documents, plans, or deliverable artifacts","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"server/src/routes/issues.ts","lineNumber":5091,"sourceCode":"      return false;\n    }\n    if (scope.companyId !== companyId) {\n      res.status(403).json({ error: \"Task-watchdog product bug follow-up target is outside the watchdog company\" });\n      return false;\n    }\n\n    const sourceIssue = await svc.getById(scope.watchedIssueId);\n    if (!sourceIssue || sourceIssue.companyId !== companyId) {\n      res.status(404).json({ error: \"Watched source issue not found\" });\n      return false;\n    }\n    const watchdogIssue = scope.watchdogIssueId ? await svc.getById(scope.watchdogIssueId) : null;\n    if (watchdogIssue && watchdogIssue.companyId !== companyId) {\n      res.status(403).json({ error: \"Task-watchdog product bug evidence issue is outside the watchdog company\" });\n      return false;\n    }\n\n    return { scope, discovery, sourceIssue, watchdogIssue };\n  }\n\n  function isStatusOnlyRecoveryContext(contextSnapshot: unknown) {\n    if (!contextSnapshot || typeof contextSnapshot !== \"object\" || Array.isArray(contextSnapshot)) return false;\n    const context = contextSnapshot as Record<string, unknown>;\n    return context.recoveryIntent === \"status_only\" &&\n      context.allowDeliverableWork === false &&\n      context.allowDocumentUpdates === false &&\n      context.resumeRequiresNormalModel === true;\n  }\n\n  async function loadActorRunContext(req: Request, companyId: string) {\n    if (req.actor.type !== \"agent\") return null;\n    const runId = req.actor.runId?.trim();\n    if (!runId) return null;\n    const run = await db\n      .select({\n        id: heartbeatRuns.id,","sourceCodeStart":5073,"sourceCodeEnd":5109,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/routes/issues.ts#L5073-L5109","documentation":"The acting run's context snapshot marks it as a cheap status-only recovery run, which is forbidden from touching issue documents, plans, or deliverable artifacts — only status/comment updates are permitted.","triggerScenarios":"Thrown at server/src/routes/issues.ts:4935 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["This is an authorization rule, not a bug: perform the action with an actor that satisfies the stated constraint (board user, the owning agent, or an in-scope resource).","If access should be allowed, verify the actor's credentials/company scope and the resource's ownership before retrying."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}