Gate stale-run watchdog decisions by board access (#4446)

## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - The run ledger surfaces stale-run watchdog evaluation issues and
recovery actions
> - Viewer-level board users should be able to inspect status without
getting controls that the server will reject
> - The UI also needs enough board-access context to know when to hide
those decision actions
> - This pull request exposes board memberships in the current board
access snapshot and gates watchdog action controls for known viewer
contexts
> - The benefit is clearer least-privilege UI behavior around recovery
controls

## What Changed

- Included memberships in `/api/cli-auth/me` so the board UI can
distinguish active viewer memberships from operator/admin access.
- Added the stale-run evaluation issue assignee to output silence
summaries.
- Hid stale-run watchdog decision buttons for known non-owner viewer
contexts.
- Surfaced watchdog decision failures through toast and inline error
text.
- Threaded `companyId` through the issue activity run ledger so access
checks are company-scoped.
- Added IssueRunLedger coverage for non-owner viewers.

## Verification

- `pnpm exec vitest run --project @paperclipai/ui
ui/src/components/IssueRunLedger.test.tsx`
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm --filter @paperclipai/ui typecheck`

## Risks

- Medium-low risk. This is a UI gating change backed by existing server
authorization.
- Local implicit and instance-admin board contexts continue to show
watchdog decision controls.
- No migrations.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, GPT-5 coding agent, tool-enabled with
shell/GitHub/Paperclip API access. Context window was not reported by
the runtime.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Dotta 2026-04-24 19:25:23 -05:00 committed by GitHub
parent 6916e30f8e
commit 73fbdf36db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 97 additions and 2 deletions

View file

@ -837,6 +837,7 @@ const IssueDetailChatTab = memo(function IssueDetailChatTab({
type IssueDetailActivityTabProps = {
issueId: string;
companyId: string;
issueStatus: Issue["status"];
childIssues: Issue[];
agentMap: Map<string, Agent>;
@ -850,6 +851,7 @@ type IssueDetailActivityTabProps = {
function IssueDetailActivityTab({
issueId,
companyId,
issueStatus,
childIssues,
agentMap,
@ -941,6 +943,7 @@ function IssueDetailActivityTab({
<div className="mb-3">
<IssueRunLedger
issueId={issueId}
companyId={companyId}
issueStatus={issueStatus}
childIssues={childIssues}
agentMap={agentMap}
@ -3410,6 +3413,7 @@ export function IssueDetail() {
{detailTab === "activity" ? (
<IssueDetailActivityTab
issueId={issue.id}
companyId={issue.companyId}
issueStatus={issue.status}
childIssues={childIssues}
agentMap={agentMap}