{"record":{"id":"a4630956a05e6ae8","repo":"paperclipai/paperclip","slug":"task-watchdog-runs-cannot-change-watchdog-configur","errorCode":null,"errorMessage":"Task-watchdog runs cannot change watchdog configuration.","messagePattern":"Task-watchdog runs cannot change watchdog configuration\\.","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"server/src/routes/issues.ts","lineNumber":4321,"sourceCode":"      identifier?: string | null;\n    },\n    options: { allowVisibleIssueWrite?: boolean } = {},\n  ) {\n    if (req.actor.type !== \"agent\") return true;\n    const actorAgentId = req.actor.agentId;\n    if (!actorAgentId) {\n      res.status(403).json({ error: \"Agent authentication required\" });\n      return false;\n    }\n    // Task-watchdog runs receive a scoped *grant* to mutate issues inside the\n    // watched subtree. This must be evaluated before the base assignee-ownership\n    // boundary below: that boundary denies an agent mutating an issue owned by a\n    // different agent, which is exactly the watchdog's primary job\n    // (SPEC-implementation §9.9 — comment, transition, reassign within the\n    // watched subtree). The watchdog scope can only widen access to the watched\n    // subtree; downstream status-transition, assignment, recovery, and budget\n    // guards in the route handlers still apply.\n    const watchdogScope = await resolveTaskWatchdogMutationScope(db, req.actor);\n    if (watchdogScope.kind !== \"none\") {\n      const scopeResult = await taskWatchdogScopeAllowsIssueMutation(db, watchdogScope, issue);\n      if (scopeResult.kind === \"invalid\") {\n        res.status(403).json({\n          error: scopeResult.detail,\n          details: {\n            issueId: issue.id,\n            securityPrinciples: [\"Least Privilege\", \"Complete Mediation\", \"Fail Securely\"],\n          },\n        });\n        return false;\n      }\n      return assertFreshTaskWatchdogSourceMutation(res, watchdogScope, issue);\n    }\n    const boundaryDecision = await decideIssueAccess(req, issue, \"issue:mutate\");\n    if (!boundaryDecision.allowed) {\n      return denyIssueWrite(req, res, issue, issueWriteDenialCodeForDecision(boundaryDecision));\n    }","sourceCodeStart":4303,"sourceCodeEnd":4339,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/routes/issues.ts#L4303-L4339","documentation":"403 from rejectTaskWatchdogConfigMutation: the mutating request comes from a task-watchdog run context, and watchdog-scoped runs are not allowed to change watchdog configuration itself.","triggerScenarios":"Thrown at server/src/routes/issues.ts:4157 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-14T05:17:10.506Z"}