Skip to content

feat(dashboard): make the live board actionable - #67

Open
RedStar071 wants to merge 10 commits into
mainfrom
feat/dashboard-live-control
Open

feat(dashboard): make the live board actionable#67
RedStar071 wants to merge 10 commits into
mainfrom
feat/dashboard-live-control

Conversation

@RedStar071

@RedStar071RedStar071 commented Sep 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Add live dashboard updates through a server-sent event stream and polling-backed overview refreshes.
  • Let operators create tasks, inspect live status, and approve or reject pending decisions from the board.
  • Add pull-request discovery without requiring a public webhook endpoint.
  • Add zero run --remote for dispatching work to a deployment's control plane.
  • Add dev:solo for running the dashboard with in-memory authentication and no Postgres.
  • Move audit-log access into the typed oRPC router and update the dashboard composables accordingly.

Why

This makes the dashboard a usable control surface instead of a read-only snapshot. Operators can see control-plane activity as it happens, create work, and resolve approval requests from the same interface.

The changes preserve the repository boundaries: the dashboard composes the API and authentication layers, runtime execution remains behind the runner, and remote CLI runs are submitted to the deployment control plane rather than executed locally. Polling provides a webhook-independent path for discovering pull requests while sharing durable delivery claims with webhook processing.

Verification

  • aube run check:repo
  • aube run lint:ci
  • aube run typecheck
  • aube test
  • aube run build

Safety and compatibility

  • I added or updated deterministic tests for changed behavior.
  • I preserved observe mode as read-only, or explained the policy change above.
  • Runtime commands and target-repository writes remain inside the runner boundary.
  • I did not expose secrets, tokens, personal data, or untrusted output in logs.
  • I updated documentation and Agent Skills when workflows or boundaries changed.

Agent context

  • Agent/tools used: AI coding agent session; repository inspection and patch review.
  • What the agent did, and what you changed or verified yourself: The agent helped author and review the change across the dashboard, API, CLI, source-control, documentation, and local-development configuration. Deterministic unit and component tests were added or updated for the changed behavior.

Reviewer notes

The change spans the dashboard control loop, audit routing, remote CLI execution, pull-request polling, and solo development setup. Particular attention is warranted for authentication and authorization behavior, polling delivery claims, remote-run repository allow-listing, and the restriction of unattended polling to non-writable modes.

Base branch: main

Confidence Score: 0/5

Unsafe to merge: four independently reproduced failures affect task execution, review coverage, CLI correctness, and service availability.

The reproduced findings include duplicate task creation, incomplete pull-request discovery, successful CLI completion for incomplete remote responses, and an authenticated resource-exhaustion path.

Files Needing Attention: apps/dashboard/server/utils/poller.ts, packages/source-control/src/providers/github-pulls.ts, packages/cli/src/remote.ts, apps/dashboard/server/api/events.get.ts, code, and vscode_cli.tar.gz.

Security Review

Authenticated users can open and retain unlimited live-event streams. Each stream allocates a listener and heartbeat scheduling resources, allowing repeated connections to consume application resources and degrade service for other users.

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced a proof for the first P1 finding and linked it to its review comment.
  • T-Rex produced a proof for a posted P2 finding.
  • T-Rex generated a general-contract-validation-proof detailing poller and proactive webhook handling, with related code and logs.
  • T-Rex generated a general-contract-validation-proof describing the SSE-cap reproduction and runtime results.
  • T-Rex produced a general-contract-validation-proof documenting the remote-task provenance and exact executed repro source.

View all artifacts

T-Rex Ran code and verified through T-Rex

Fix all with GreploopFix All in Claude CodeFix All in CursorFix All in Cursor Cloud Agents

Prompt To Fix All With AI
### Issue 1
apps/dashboard/server/utils/poller.ts:74
**Share pull request claims**
Polling claims a commit under `poll:<repo>#<number>@<headSha>`, but a GitHub `pull_request` synchronize delivery for that same commit starts another task without checking that claim. A poll followed by the matching webhook creates two reviews for one revision, duplicating model work and review activity. Use one atomic pull-request-and-commit claim across both intake paths.
### Issue 2
packages/source-control/src/providers/github-pulls.ts:225-235
**Paginate pull request discovery**
Each polling pass requests the same first 50 open pull requests ordered by most recently updated, with no page, cursor, or rotation state. An open pull request ranked 51st or later is never sent to the poller unless it later becomes recent enough to enter that first page, so eligible reviews can be missed indefinitely. Advance through pages or persist a bounded rotating cursor.
### Issue 3
packages/cli/src/remote.ts:118-119
**Reject incomplete remote results**
The remote-result guard accepts `{ "id": "task-queued", "state": "queued" }` as a completed task result even though downstream code requires a terminal state and complete result fields. In JSON mode, the CLI prints that partial response and exits successfully, allowing CI to report success before a review has completed; normal output instead throws while rendering the missing plan. Reject non-terminal or incomplete responses before reporting them.
### Issue 4
apps/dashboard/server/api/events.get.ts:56-60
**Limit live event connections**
Any authenticated account can retain an unlimited number of live event streams. Each accepted request creates an open stream, a process-wide task-change listener, and heartbeat scheduling, while the listener warning limit is disabled. Repeated connections can exhaust application resources and degrade service for other users; enforce per-user and global connection limits or rate limiting.
**How this was verified:** Retaining twelve authenticated streams created twelve listeners and twelve heartbeat allocations without an application-level connection cap.
### Issue 5
code:1
**Remove duplicate CLI artifacts**
This change adds a 34,190,560-byte root-level `code` executable and a 12,689,426-byte `vscode_cli.tar.gz` containing the identical executable. Neither artifact is referenced by the changed dashboard, API, CLI, polling, or documentation paths. This is non-blocking functionality-wise, but it permanently adds roughly 47 MB of duplicate binary history and increases checkout and repository costs. Remove both artifacts unless a documented workflow requires one canonical distribution.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "chore: add VS Code CLI binaries" | Re-trigger Greptile

Greptile also left 4 inline comments on this PR.

Context used (5)

RedStar071and others added 10 commits September 5, 2026 17:32
Records what was verified by building and running the app on 2026-09-05: the
dashboard renders and the control plane executes runs, but nothing feeds it,
nothing refreshes it, and starting it needs a database.
The plan restructures the edge rather than the packages, in five phases with a
demonstrable exit criterion each.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Seeing the dashboard required Postgres, a migration, a signing secret, and
control-plane tokens before the first page could render, so the quickest way to
look at it was not to.
`dev:solo` is `nuxt dev --dotenv .env.solo`: the same app, the same router, and
the same `/api/auth/**` endpoints, with Better Auth on the in-memory store the
Playwright preview server already uses. `.env.solo` is checked in because it
holds nothing worth keeping out of the repository — the session store dies with
the process, and the control-plane token is only accepted by a server started
this way. It is loaded only when a command names it with `--dotenv`, so `.env`
and every deployment are untouched.
Verified: `turbo run dev:solo --filter=@code-zero/dashboard` from a checkout with
no database — `/api/v1/health` 200, `/login` 200, `POST /api/auth/sign-up/email`
returns a session, and `/` renders Control Plane with that cookie. check:repo,
format:check, and typecheck pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The trail had two homes it did not need. Recording went through a hand-rolled
`AuditRecorder` injected into the RPC context, while `evlog` — already installed,
already wrapping both transports — has an audit pipeline with the same shape.
Reading lived in a Nitro route outside the router, written when the router could
not authenticate a browser session; since it can, that reason is gone.
Recording is now `log.audit()` / `log.audit.deny()`. The persisted record is
evlog's own `AuditFields` plus a storage id and timestamp, so there is no second
audit vocabulary to keep in step, and `auditEnricher` fills in request context
(`requestId`, `traceId`, ip, user agent) no call site had been passing. The
identity is evlog's deterministic `idempotencyKey`, so a retried delivery lands
on the key it already wrote instead of appending a second copy. `auditLogPlugins`
carries the record to the same KV-backed store as before, filtered by
`auditOnly` and awaited so an audited mutation cannot answer 200 and lose its
record, and installed as `EvlogHandlerPlugin` plugins rather than as its `drain`,
so a deployment's own request logging is untouched.
Reading is `audit.list`, an authenticated procedure gated on a new explicit
`Principal.admin` rather than on a mode grant: what a caller may run and what a
caller may see are different questions. Operator tokens are never
administrators — the trail records their use, so letting one read it back would
let a token audit itself.
Verified against the built server: `tasks.create` success and denial each
persisted one record carrying `context.requestId` and the user agent; `audit.list`
answered FORBIDDEN for an operator token and for a signed-in non-admin over
`/rpc/**`. lint:ci, typecheck, and 151 api tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The board showed whatever the last fetch caught. A run records its lifecycle
events as it works, so a task appeared and then sat at the state it had when the
page loaded until someone pressed refresh — and a stalled page looked exactly
like a quiet one.
`/api/events` streams the overview over SSE, behind the same session the page
needs, pushing whenever a task record is written. The store wrapper that emits
lives in the composition root rather than in `packages/api`, so the store
contract stays plain persistence: every writer — the router, the webhook route,
and the run recording its own events — already goes through that one instance,
so a subscriber sees the whole lifecycle rather than the transitions one
transport happens to see. Writes are coalesced over 250ms, so a run that records
ten events in a burst sends one overview.
The client writes each message straight into the query cache the page already
reads, rather than invalidating and asking the server for what it just sent. The
query stays the loader for the first paint and for a client whose stream never
opens. A header indicator says whether the board is actually following, because
a stalled stream is otherwise indistinguishable from an idle one.
`useLiveOverview` takes the query key rather than reaching for `useNuxtApp()`,
which is also what keeps it out of the Nuxt runtime for the unit suite.
Verified against the built server: the stream answers 401 unauthenticated; with
a session it pushes the current overview on connect and again when a task
created through `/api/v1/tasks` reached the store. lint:ci, typecheck, i18n:report,
and the dashboard suites pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The router has accepted `tasks.create` and `approvals.decide` since the control
plane existed, but nothing in the UI called either: the board could watch a run
stop for a human decision and offer no way to give one. The sidebar meanwhile
listed nine sections that were inert buttons — a nav that promises surfaces the
app does not have teaches an operator that clicking does nothing.
The inspector offers Approve and Reject with an optional comment while a task is
`needs-human` and undecided, and shows the recorded decision once one exists,
because the control plane accepts exactly one. A `details`-based form queues a
task from the header. Both emit rather than mutate: the page owns the typed
client and the one place a failure is surfaced, so there is no second path to
keep in step. Neither writes into the query cache — the decision lands in the
store, and the store is what the live stream pushes back, so the board updates
from the same source every client sees rather than from a guess about what the
server did.
The repository is typed rather than picked from the allow-list: the list is
server-side checkout paths, which the persisted records deliberately keep out of
reach, and `tasks.create` already names the rule it refused on.
Verified against the built server, over the same `/rpc/**` the page uses: a
session created a task, and got FORBIDDEN for a repository outside the allow-list
and for a mode a session may not request. The approval and form logic are covered
by 13 new component tests. Browser verification of the rendered result was not
possible — this environment has no automation host — so the visual pass against
`nuxt-frontend-review` is still owed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Work only reached the control plane when a provider delivered it, so a
self-hosted deployment behind no public URL had nothing feeding it: the board
stayed empty unless someone posted a task by hand.
`server/plugins/poller.ts` lists each watched repository's open pull requests on
an interval and starts a review for every head commit it has not started one
for. It is the pull-based half of the job the webhook route already does, and it
shares that route's durable `DeliveryClaimStore`, so a commit reviewed through
one path is never reviewed again through the other. The claim key carries the
head sha, which is what makes a new push earn a new review and an unchanged pull
request earn nothing.
Constraints that are enforced, not documented: it is off unless
`CODE_ZERO_POLL_REPOSITORIES` names something; it requests only `observe` or
`suggest`, so work nobody asked for cannot write to a checkout; and the checkout
comes from the path an operator paired with the repository rather than being
derived from the provider's answer, so a run can never target somewhere nobody
named. A failed start releases its claim so the next pass retries, and one
unreachable provider does not end the pass.
`listOpenPullRequests` is new on the GitHub adapter and returns both the base and
head commits, because a review reads the diff between them. It skips a record
missing either rather than losing the page it arrived in.
Verified against the built server: silent and healthy when unconfigured; refuses
to start naming the missing variable when configured without a token; and with a
token it reports the repository that failed without stopping the process or
putting the credential in the log. A pass against real GitHub is still owed —
this environment has no credentials, and the tests deliberately reach no network.
27 new tests; lint:ci, typecheck across the graph, and the build pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`accessFromEnvironment` returned `undefined` unless `CODE_ZERO_CONTROL_PLANE_TOKENS`
was set, and `mayTargetRepository` fails closed without a policy. So a deployment
that authenticates only browser sessions could never create a task: the
`CODE_ZERO_CONTROL_PLANE_REPOSITORIES` it had configured did not exist as far as
the router was concerned, and every target was refused.
The two variables answer different questions. Tokens say who a machine caller
is; the allow-list says what any authenticated caller may target, including a
person signed into the dashboard. Either one now produces a policy, and only
neither returns `undefined`, so an unconfigured deployment still rejects every
mutation and a deployment with no tokens still authenticates no machine caller —
`principals` is simply empty.
Found by running the dashboard with a session and an allow-list and nothing else,
which is what `dev:solo` and a self-hosted single-owner install both look like.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A local `zero run` and the dashboard kept separate histories: the CLI executed in
the checkout and recorded nothing the board could read, so work started from a
terminal was invisible to the surface built to watch it.
`--remote` hands the run to a deployment's control plane instead. It presents the
session `zero login` stored as a bearer token, so the run is attributed to the
person who signed in rather than to a shared operator token, and it goes to
`/rpc/**` because that is the only transport that resolves a session — stating
the `Sec-Fetch-Mode` header its CSRF guard reads, which a browser sends on its
own. The deployment therefore needs `AUTH_ENABLE_DEVICE_AUTHORIZATION=true`, the
same flag `zero login` already requires.
A flag rather than an inference from `CODE_ZERO_URL`: that variable already
selects which deployment `login` and `logout` act on, so treating its presence as
"run somewhere else" would silently move an operator's run to another machine and
another checkout the first time they set it. The plan called for the implicit
form; this is the deliberate departure from it.
The exit code comes from the same table a local run uses, so CI reads either the
same way, and an answer that is not a result is refused rather than allowed to
exit 0.
Verified against the built server end to end: from a checkout, `zero run
--proactive --remote --json` authenticated with a stored session, executed on the
deployment, printed the result, exited 0, and the task appeared in the board's
own `dashboard.overview`. 14 new tests; lint:ci and typecheck pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The whole live board rests on one property — every task write announces itself —
and nothing tested it. It could not be tested either: the notification was a
subclass of the KV-backed store, so reaching it meant reaching the deployment's
filesystem driver.
`observeWrites` is that subclass turned into a decorator over any `TaskStore`, so
a test drives it against an in-memory one. The tests state the parts that matter:
it announces every write, only after the write landed, and says nothing when the
write failed — a listener re-reading the store on a failed write would find
nothing changed and a listener told too early would read the previous state.
Forwarding `clear` went with it: `PersistentTaskStore` has none, so it was a
capability the wrapper invented for nobody.
`docs/architecture.md` gains the live-state paragraph the plan asked for, and
`docs/PLAN.md` records what was built, the three places the plan was departed
from and why, and the five things still owed — the browser review among them.
Verified: 997 tests across every package and app, lint:ci, typecheck, check:repo,
i18n:report, and the build all pass. The docs build needs a larger heap than this
sandbox allows by default and passes with one; nothing in this branch touches it
beyond a one-line table.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Add the `code` executable and VS Code CLI archive
@vercel

vercelBot commented Sep 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated
agent-zero-dashboardBlockedBlockedSep 5, 2026 8:35pm UTC
agent-zero-docsReadyReadyPreviewSep 5, 2026 8:35pm UTC
agent-zero-marketingReadyReadyPreviewSep 5, 2026 8:35pm UTC


for (const pull of open) {
if (pull.draft) continue;
const key = pollClaimKey(repository, pull);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1Share pull request claims

Polling claims a commit under poll:<repo>#<number>@<headSha>, but a GitHub pull_request synchronize delivery for that same commit starts another task without checking that claim. A poll followed by the matching webhook creates two reviews for one revision, duplicating model work and review activity. Use one atomic pull-request-and-commit claim across both intake paths.

Knowledge Base Used:

Artifacts

Evidence from the check

  • Targeted source used to create one proactive poll task for PR 67 at the fixed head SHA, showing the poll claim scope.

Command output from the check

  • Executed poll-only command from `/home/user/repo` exited 0 and recorded one task with claim key `poll:acme/app#67@<headSha>`.

Evidence from the check

  • Targeted reproduction source for the shared-store poll followed by the signed GitHub synchronize delivery.

Command output from the check

  • Executed poll followed by the same-commit synchronize webhook from `/home/user/repo/apps/dashboard` exited 0; the webhook returned HTTP-equivalent 200 accepted and task count rose from one to two.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/dashboard/server/utils/poller.ts
Line: 74
Comment:
**Share pull request claims**
Polling claims a commit under `poll:<repo>#<number>@<headSha>`, but a GitHub `pull_request` synchronize delivery for that same commit starts another task without checking that claim. A poll followed by the matching webhook creates two reviews for one revision, duplicating model work and review activity. Use one atomic pull-request-and-commit claim across both intake paths.
**Knowledge Base Used:**-[Application service API](https://app.greptile.com/wolfstar-project/-/custom-context/knowledge-base/wolfstar-project/code-zero/-/docs/service-api.md)-[Dashboard application](https://app.greptile.com/wolfstar-project/-/custom-context/knowledge-base/wolfstar-project/code-zero/-/docs/dashboard-application.md)---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude CodeFix in CursorFix in Cursor Cloud Agents

Comment on lines +225 to +235
async listOpenPullRequests(target: RepositoryTarget, perPage = 50): Promise<OpenPullRequest[]> {
const query = new URLSearchParams({
state: 'open',
sort: 'updated',
direction: 'desc',
per_page: String(Math.min(Math.max(Math.trunc(perPage), 1), 100)),
});
const payload = await this.send(
'GET',
`/repos/${target.owner}/${target.repo}/pulls?${query.toString()}`,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1Paginate pull request discovery

Each polling pass requests the same first 50 open pull requests ordered by most recently updated, with no page, cursor, or rotation state. An open pull request ranked 51st or later is never sent to the poller unless it later becomes recent enough to enter that first page, so eligible reviews can be missed indefinitely. Advance through pages or persist a bounded rotating cursor.

Knowledge Base Used:Source-control provider adapters

Artifacts

Evidence from the check

  • The exact TypeScript reproduction executed against the baseline commit and current GitHub pull-request adapter, showing that repeated calls omit pagination. The takeaway is that the proof is deterministic and directly exercises the adapter.

Command output from the check

  • Captured execution output from the parent of the introducing commit, where `listOpenPullRequests` did not yet exist and therefore made no HTTP request. The takeaway is that the before state has no comparable endpoint behavior.

Command output from the check

Command output from the check

  • Captured verbose Vitest output for the GitHub pull-request adapter tests, with all 15 tests passing. The takeaway is that existing tests do not cover advancing beyond the first page.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/source-control/src/providers/github-pulls.ts
Line: 225-235
Comment:
**Paginate pull request discovery**
Each polling pass requests the same first 50 open pull requests ordered by most recently updated, with no page, cursor, or rotation state. An open pull request ranked 51st or later is never sent to the poller unless it later becomes recent enough to enter that first page, so eligible reviews can be missed indefinitely. Advance through pages or persist a bounded rotating cursor.
**Knowledge Base Used:**[Source-control provider adapters](https://app.greptile.com/wolfstar-project/-/custom-context/knowledge-base/wolfstar-project/code-zero/-/docs/source-control-providers.md)---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude CodeFix in CursorFix in Cursor Cloud Agents

Comment on lines +118 to +119
function isTaskResult(value: unknown): value is TaskResult {
return isRecord(value) && typeof value.id === 'string' && typeof value.state === 'string';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1Reject incomplete remote results

The remote-result guard accepts { "id": "task-queued", "state": "queued" } as a completed task result even though downstream code requires a terminal state and complete result fields. In JSON mode, the CLI prints that partial response and exits successfully, allowing CI to report success before a review has completed; normal output instead throws while rendering the missing plan. Reject non-terminal or incomplete responses before reporting them.

Knowledge Base Used:Command-line client

Artifacts

Evidence from the check

  • A local HTTP server and isolated credential store run the built CLI against complete and partial RPC responses, ending with the reproduced contract failure.

Command output from the check

  • The complete TaskResult `HTTP/1.1 200 OK` baseline was requested through the real built CLI and exited 0, establishing expected terminal behavior.

Command output from the check

  • The partial queued `HTTP/1.1 200 OK` result was accepted: JSON mode exited 0 and ordinary mode failed while rendering evidence, confirming the defect.

Command output from the check

  • The existing focused CLI suite was executed after the repro and passed 64 tests, showing current tests do not cover this partial-result contract.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/cli/src/remote.ts
Line: 118-119
Comment:
**Reject incomplete remote results**
The remote-result guard accepts `{ "id": "task-queued", "state": "queued" }` as a completed task result even though downstream code requires a terminal state and complete result fields. In JSON mode, the CLI prints that partial response and exits successfully, allowing CI to report success before a review has completed; normal output instead throws while rendering the missing plan. Reject non-terminal or incomplete responses before reporting them.
**Knowledge Base Used:**[Command-line client](https://app.greptile.com/wolfstar-project/-/custom-context/knowledge-base/wolfstar-project/code-zero/-/docs/command-line-client.md)---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude CodeFix in CursorFix in Cursor Cloud Agents

Comment on lines +56 to +60
const heartbeat = setInterval(() => {
if (!closed) void stream.push({ event: 'heartbeat', data: '' }).catch(() => undefined);
}, HEARTBEAT_MS);

taskChanges.on(TASK_CHANGED, schedulePush);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1securityLimit live event connections

Any authenticated account can retain an unlimited number of live event streams. Each accepted request creates an open stream, a process-wide task-change listener, and heartbeat scheduling, while the listener warning limit is disabled. Repeated connections can exhaust application resources and degrade service for other users; enforce per-user and global connection limits or rate limiting.

How this was verified: Retaining twelve authenticated streams created twelve listeners and twelve heartbeat allocations without an application-level connection cap.

Artifacts

Evidence from the check

  • Executable source that captured the route response before the event-stream endpoint was added.

Command output from the check

  • Captured output showing that GET `/api/events` returned 404 before this event-stream endpoint was introduced.

Evidence from the check

  • Executable source that opens and retains authenticated event streams while measuring listener and timer allocations.

Command output from the check

  • Captured output showing twelve accepted streams for one authenticated user with twelve retained listeners and heartbeat allocations.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/dashboard/server/api/events.get.ts
Line: 56-60
Comment:
**Limit live event connections**
Any authenticated account can retain an unlimited number of live event streams. Each accepted request creates an open stream, a process-wide task-change listener, and heartbeat scheduling, while the listener warning limit is disabled. Repeated connections can exhaust application resources and degrade service for other users; enforce per-user and global connection limits or rate limiting.
**How this was verified:** Retaining twelve authenticated streams created twelve listeners and twelve heartbeat allocations without an application-level connection cap.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude CodeFix in CursorFix in Cursor Cloud Agents

@macroscopeapp

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR adds several production workflows—live SSE updates, background pull-request polling, remote execution, audit access, and dashboard mutations—alongside authentication and access-policy changes. Unresolved findings identify duplicate or missed reviews, incomplete remote results, and unlimited live connections, so the scope and risk require human review.

Not approved because:

  • Credit balance exhausted. Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@RedStar071