Skip to content

fix(automation): surface failed sync responses on repo detail page - #1387

Merged
joryirving merged 2 commits into
mainfrom
courier/misospace/dispatch/issue-1385
Oct 24, 2026
Merged

joryirving merged 2 commits into
mainfrom
courier/misospace/dispatch/issue-1385

Conversation

@itsmiso-ai

@itsmiso-ai itsmiso-ai commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #1385.

The repo detail "Sync" button posted to POST /api/automation/sync and then unconditionally reloaded the page without checking res.ok, so failed or throttled responses (e.g. the 429 {"error":"Rate limit exceeded"} from #1307, the 409 "already running" lock, or a 500 {error} body) were silently hidden by the reload. This mirrors the fix already open in #1384 exactly: check res.ok, parse the error body (data?.error || 'Failed to sync (HTTP <status>)'), render the error on the page, reload only on success, disable the button while syncing, and spin the refresh icon. Applied to src/app/automation/repos/[...repo]/page.tsx only — the #1324/#1384 scope was src/app/automation/page.tsx, per that issue's accepted scope.

Changes

Issue fix (05126ab)

  • src/app/automation/repos/[...repo]/page.tsx
    • Added syncing/syncError state and an async handleSync(fullName) handler: throws on !res.ok with the API error body (falling back to HTTP status text for non-JSON bodies), catches into rendered error text via the error instanceof Error pattern, reloads only on success.
    • Sync button now disabled={syncing} with a spinning RefreshCw while in flight.
    • Error renders in the header area (uses the already-imported AlertTriangle).

npm audit gate fix (71520e8)

  • package-lock.json only. The blocking npm run audit CI gate (prod deps, --audit-level=high) failed on the pre-existing lock — package-lock.json was byte-identical to main, and this PR's UI change touches no dependencies — on body-parser 2.3.0 (high, GHSA-27r3-jxmh-p828: DoS via trailing bytes after a compressed request body) plus moderates hono 4.13.7 (GHSA-5r4p-p66f-jhc7) and ip-address 10.7.2 (GHSA-rxp7-6hxx-x8q5).
  • npm audit fix --package-lock-only --include=prod bumps body-parser → 2.4.0, hono → 4.13.13, ip-address → 10.7.4, qs → 6.16.1; npm also re-resolved the dev-only tree (vite 8.3.0→8.3.5, rolldown 1.2.8→1.2.15, @oxc-project/types, @rolldown/* bindings). Every bump stays inside the existing semver ranges (package.json untouched, verified by npm ci succeeding on the refreshed lock). Mechanical lockfile bump — skipped a separate review pass per the mech-bump review discipline; validation covers it.

Local validation (run once per final change state, worktree HEAD 71520e8)

  • npm ci --include=dev — exit 0 (validates lock/package consistency)
  • npm run audit — exit 0; "found 0 vulnerabilities" (the previously failing gate)
  • npm run typecheck — exit 0
  • npm run lint — exit 0; 0 errors, 1 pre-existing warning in src/app/login/page.tsx (unrelated, pre-dates this change)
  • npm run test (Vitest) — exit 0 (full suite green after the lock refresh)

State prior to the audit fix, HEAD 05126ab: lint (0 errors, same pre-existing warning), typecheck, and vitest (206 files passed | 5 skipped, 5317 tests | 27 skipped | 1 todo) all exit 0.

Review

One bounded adversarial reviewer pass on the UI diff — PASS, no blockers/majors (verified error-path contract against src/app/api/automation/sync/route.ts and rate limiting, double-click protection, TS narrowing on nullable repo state). Limitation: all roles on this lane run the same model, so no model-diverse independent review. The lockfile-only audit-fix commit was validated rather than re-reviewed (in-range bump, mechanical).

Remaining external verification

  • CI (lint/typecheck/build/test + npm audit) on head 71520e8 is pending; not awaited by this run — operator verifies after exit. The npm audit failure seen on the previous head (05126ab) was reproduced and fixed locally; expect that check green on the new head.
  • Two INFO follow-ups not in this issue's accepted scope, tracked as: (1) the per-run workflow rerun button on this same page (authedFetch(.../runs/<id>?...&action=rerun).then(() => reload())) has the same silent-reload pattern; (2) PR fix(automation): surface failed/in-progress per-repo sync responses (#1324) #1384 must merge for the overview page.

its-saffron[bot]

This comment was marked as outdated.

npm audit --omit=dev (blocking CI gate) failed on main and on this PR
head: body-parser 2.3.0 was high (GHSA-27r3-jxmh-p828, DoS via trailing
bytes after a compressed body), hono 4.13.7 and ip-address 10.7.2 were
moderate.

npm audit fix --package-lock-only --include=prod bumps body-parser to
2.4.0, hono to 4.13.13, ip-address to 10.7.4 and qs to 6.16.1; npm also
re-resolved the dev tree (vite, rolldown, @oxc-project/types and
@rolldown/* bindings) inside the same existing ranges. package.json and
every range are unchanged; package-lock.json was already identical to
main before this commit, so the failure pre-dates this PR.

Local validation at this change state: npm ci --include=dev, npm run
audit (0 vulnerabilities), typecheck, lint (1 pre-existing warning) and
vitest all exit 0.

@its-saffron its-saffron Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AI Automated Review

Full PR review.

Analysis engine: MiniMax-M3.1-Flash (anthropic) — primary route · pr-reviewer-action v3.7.0

Recommendation: Approve.

Linked Issue Fit

The implementation satisfies the linked issue: non-OK JSON responses expose their error field, invalid/non-JSON responses receive an HTTP-status fallback, the page does not reload after failure, and the button is disabled while the request is in flight. The route contract confirms JSON errors for rate limiting, lock conflicts, and sync failures.

Claims

The functional UI claims held across the identified implementation points; the only wording discrepancy is that the non-JSON fallback contains the numeric HTTP status rather than Response.statusText. The audit and follow-up-scope claims also held based on the lockfile diff and unchanged rerun path, although external tracking of that follow-up was not independently verified.

Required Checks

  • check for breaking API changes in updated dependencies — satisfied: the lock-only changes retain compatible semver lines, the affected transitive packages have no direct imports in src, and build, typecheck, lint, and tests all succeeded.
  • run full test suite after upgrade — satisfied: the CI Tests check succeeded on the PR head.

Tool Harness Findings

Direct reads verified the changed page, sync API contract, client authentication, package manifest, lockfile dependency graph, audit guard, and rate-limit response shape. The GitHub check-runs API request failed because that transport was unavailable, but the supplied CI results cover the required checks.

Sources

Reviewed the changed page, src/app/api/automation/sync/route.ts, src/lib/client-auth.ts, src/lib/rate-limit.ts, package.json, package-lock.json, and the upstream body-parser advisory: GHSA-27r3-jxmh-p828

Unknowns or Needs Verification

Detailed upstream changelogs for every transitive version were not retrieved before the tool budget was exhausted, and no external tracking record for the out-of-scope rerun follow-up was available.

@joryirving joryirving left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Secondary hard-blocker review on exact head 71520e85f7057d68d89fcf63fec7636d39cfba20: APPROVE. The repo-detail sync handler checks res.ok, surfaces API errors with a safe status fallback, prevents reload on failure, and disables the button while the request is in flight. The lockfile-only dependency refresh stays within existing package semver ranges and resolves the known production audit gate; CI, build, smoke, Security Audit, and AI review are all green on this exact head. The missing dedicated UI regression test is a minor follow-up, not a blocker.

@joryirving
joryirving merged commit f1adeca into main Oct 24, 2026
13 checks passed
@joryirving
joryirving deleted the courier/misospace/dispatch/issue-1385 branch October 24, 2026 02:21
joryirving added a commit that referenced this pull request Oct 24, 2026
…1388) (#1396)

The per-run rerun button in the repo detail page's runs table used the
unguarded pattern authedFetch(...).then(() => window.location.reload())
with no res.ok check, silently hiding failed/throttled reruns (including
429 {"error":"Rate limit exceeded"}) as if they had succeeded.

Adopt the handler pattern the sibling Sync button uses (#1387, after
#1384's overview page): check res.ok, parse the JSON error body, render
it in a destructive banner above the workflows list, and only reload the
page on success. Rerun buttons disable while a rerun is in flight, with
the active run's icon spinning.
Sign up for free to 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.

Repo detail page Sync button silently ignores non-OK responses from POST /api/automation/sync

2 participants