Skip to content

fix(security): harden dashboard trust boundaries - #364

Merged
mira-2026 merged 7 commits into
mainfrom
mira/security-scan-hardening-2026-07-31
Aug 1, 2026
Merged

fix(security): harden dashboard trust boundaries#364
mira-2026 merged 7 commits into
mainfrom
mira/security-scan-hardening-2026-07-31

Conversation

@mira-2026

Copy link
Copy Markdown
Collaborator

Summary

  • harden immutable release launch/rollback integrity, production cookies and bind-host behavior, automated Git, Docker Compose discovery, and PR preview boundaries
  • bound and validate untrusted Gateway, chat, log, media, cron, skill, cache, and pull-request content across backend and frontend trust boundaries
  • preserve scoped task notifications and Delivery polling while moving destructive preview reconciliation behind an explicit recent-MFA mutation
  • align all fresh-install scheduled-job defaults with the current production database while preserving existing database schedules as the source of truth
  • pin GitHub Actions, restore keyboard focus visibility, and repair the validated operational robustness findings from the scan

Finding disposition

  • 32 findings are remediated by this branch
  • 3 findings were already fixed by the current architecture and now have explicit verification coverage
  • 7 findings are documented as intended behavior, accepted upstream limitation, not applicable, obsolete/out of scope, or duplicate/superseded

GitHub's preview stack-merge API can pin only the selected PR SHA. This branch restricts every stack layer to configured trusted authors and revalidates every expected head immediately before merge; lower-layer atomic SHA pinning remains a documented upstream API limitation.

No old-database migration path or obsolete-browser compatibility layer was added.

Preserved behavior

  • automation credentials with tasks:write can still create and update tasks and trigger Mira notifications, but automation-originated notification text contains only trusted event metadata
  • Delivery polling and automatic refresh remain enabled; the manual refresh action supplements polling for the explicit cleanup mutation
  • commit identities remain available in authenticated diagnostics and immutable local release manifests
  • existing operator-edited scheduled-job values, including explicit nulls, remain authoritative

Verification

  • bun run test:frontend — 663 passed, 0 failed
  • bun run test:backend — 708 passed, 0 failed
  • focused chat storage/page behavior — 44 passed, 0 failed
  • bun run build
  • bun run lint
  • bun run format:check
  • git diff --check

Dashboard task: #387

@mira-2026
mira-2026 requested a review from rajohan as a code owner July 31, 2026 18:49
@mira-2026 mira-2026 added priority: high High-priority work for the next active cycle status: needs-review Ready for human or agent review type: security Security, auth, secrets, or trust-boundary work area: ci CI, test runners, workflow checks, and release gates area: ops Operational actions, deploys, services, backups, and health area: frontend Frontend UI, client state, routing, and browser behavior area: backend Backend API, server routes, services, and integrations labels Jul 31, 2026
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@mira-2026, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 36 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e432dd3e-2d59-4b7c-b40b-26e99ca75c08

📥 Commits

Reviewing files that changed from the base of the PR and between 96df63c and 9b9de58.

📒 Files selected for processing (1)
  • backend/test/releaseDeployment.test.ts
📝 Walkthrough

Summary by CodeRabbit

  • Security

    • Improved protection for sensitive configuration, cookies, files, Git operations, media, and scheduled-job identifiers.
    • Added safer handling for images, attachments, and untrusted data.
  • Reliability

    • Added bounded request timeouts, safer session and timestamp handling, resilient database metrics, and improved backup scheduling.
    • Live logs and chat diagnostics now remain within defined size limits.
  • Chat

    • Improved media validation, deduplication, content limits, tool-result handling, and message stability.
  • Pull Requests & Deployments

    • Added scheduled preview reconciliation, bounded pull-request loading, and more reliable release activation and rollback behavior.
  • UI

    • Improved database metrics display, image fallbacks, and keyboard focus styling.

Walkthrough

This PR hardens Dashboard runtime behavior across release execution, Gateway requests, filesystem and route validation, service resilience, canonical chat data, frontend state, and regression coverage. It also pins GitHub Actions to immutable commits.

Changes

Dashboard hardening and runtime updates

Layer / File(s) Summary
Workflow pinning and managed release execution
.github/workflows/*, backend/src/release*, systemd/*, docs/setup/production-deploy.md
Actions use immutable commit SHAs. Managed releases include an executable launcher and run it from the current release.
Bounded Gateway and runtime handling
backend/src/gateway.ts, backend/src/lib/*, backend/src/database.ts, backend/src/gatewayToken.ts, backend/src/http.ts
Gateway requests, timestamps, sessions, tokens, cookies, and test database access use bounded or shared validation.
Request and service validation
backend/src/routes/*, backend/src/services/*
Routes validate identifiers and files. Git commands disable hooks. Service queries, previews, notifications, scheduled jobs, and quota probes use explicit state handling.
Canonical chat contracts and frontend state
contracts/chat/*, contracts/chatCanonical*, frontend/src/components/features/chat/*, frontend/src/collections/*
Chat text, tool values, images, diagnostics, media URLs, fingerprints, deletion keys, and logs receive canonical limits and normalization.
Regression coverage and build support
backend/test/*, frontend/src/test/*, package.json
Tests cover the updated release, Gateway, service, route, chat, database, and frontend behavior. Build scripts invoke tsc through the project path.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: area: auth, area: docker, area: files, area: openclaw, area: database

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the pull request’s primary security-hardening changes across dashboard trust boundaries.
Description check ✅ Passed The description provides a detailed summary, behavior coverage, findings disposition, preserved behavior, and verification results, but omits several template checklist sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
backend/test/chatCanonicalMessage.test.ts (1)

15-37: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Validate provider attachment URLs before using them.

AttachmentPreviewContent passes previewItem.url into chatImageDisplayUrl(), and that value is used as the <img src> source. The downloaded file name is taken from provider data. Reject URL values that are not data URLs or trusted dashboard origins before rendering or downloading, or explicitly document that this contract is only safe for trusted provider transcripts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/test/chatCanonicalMessage.test.ts` around lines 15 - 37, Validate
provider-supplied attachment URLs in the flow used by AttachmentPreviewContent
and chatImageDisplayUrl before rendering them as img src or using them for
downloads. Accept only data URLs or URLs from trusted dashboard origins,
rejecting arbitrary absolute or untrusted URLs; ensure the existing
canonicalChatImageDisplayUrl and related normalization paths enforce this
contract consistently.
frontend/src/components/features/chat/chatTypes.ts (1)

297-461: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Exclude SVG data URLs from the embedded raster dimension check.

embeddedChatImageDimensions only checks PNG, GIF, JPEG, and WebP bytes, so data:image/svg+xml;base64,... URLs fail isEmbeddedChatImageWithinDimensionLimit. chatImageDisplayUrl then returns undefined before reaching the SVG MIME branch, so embedded SVG images fail to render.

Exempt data:image/svg+xml from the raster gate, with SVG-specific size validation if needed.

Add a regression test for an embedded base64 SVG data URL passing through chatImageDisplayUrl.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/features/chat/chatTypes.ts` around lines 297 - 461,
Update chatImageDisplayUrl so data:image/svg+xml URLs bypass the raster-only
isEmbeddedChatImageWithinDimensionLimit check, while PNG, GIF, JPEG, and WebP
continue using it; retain any existing SVG MIME handling and apply SVG-specific
size validation if required. Add a regression test covering an embedded base64
SVG data URL that successfully passes through chatImageDisplayUrl.
🧹 Nitpick comments (6)
backend/src/services/databaseOverview.ts (1)

424-442: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log the rejected torrent-count queries.

A rejected query now reports 0. Consumers cannot distinguish an empty table from a failed probe, and the rejection reason is discarded. Add a log line for the rejected result so operators can diagnose the failure.

♻️ Proposed refactor
-    const countFromResult = (result: PromiseSettledResult<string>) =>
-        result.status === "fulfilled"
-            ? numberFrom(
-                  stringFallback(
-                      parseTable<{ count: string }>(result.value)[0]?.count,
-                      "0"
-                  )
-              )
-            : 0;
+    const countFromResult = (label: string, result: PromiseSettledResult<string>) => {
+        if (result.status === "rejected") {
+            console.warn(`Torrent count query failed for ${label}:`, result.reason);
+            return 0;
+        }
+        return numberFrom(
+            stringFallback(parseTable<{ count: string }>(result.value)[0]?.count, "0")
+        );
+    };
 
     return {
-        comet: countFromResult(cometResult),
-        bitmagnet: countFromResult(bitmagnetResult),
+        comet: countFromResult("comet", cometResult),
+        bitmagnet: countFromResult("bitmagnet", bitmagnetResult),
     };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/services/databaseOverview.ts` around lines 424 - 442, Update the
torrent-count result handling around countFromResult so rejected
Promise.allSettled results are logged with their rejection reason before
returning 0. Preserve the existing fulfilled-result parsing and zero fallback,
and use the surrounding database overview logging mechanism.
frontend/src/pages/Delivery.tsx (1)

1468-1472: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Include the pull-request refetch in the refresh button state.

isLoading tracks only reconcilePullRequestPreview.isPending. The spinner stops and the button re-enables while refetchPullRequests is still running, so a second refresh can start. Expose isFetching from usePullRequests and combine both states. Consider disabling the control while isActionPending is true, which matches the other controls in this header.

♻️ Proposed refactor
                         <RefreshButton
                             onClick={() => void refreshDelivery()}
-                            isLoading={reconcilePullRequestPreview.isPending}
+                            isLoading={
+                                reconcilePullRequestPreview.isPending ||
+                                isPullRequestsFetching
+                            }
                             label="Refresh Delivery"
                         />

Destructure the fetch state where the query is read:

     const {
         data: pullRequests = [],
         isLoading,
+        isFetching: isPullRequestsFetching,
         error,
         refetch: refetchPullRequests,
     } = usePullRequests();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/Delivery.tsx` around lines 1468 - 1472, Update the
Delivery page refresh flow around RefreshButton and usePullRequests so its
loading state remains active while either reconcilePullRequestPreview is pending
or pull-request refetching is in progress. Destructure and reuse the hook’s
isFetching state, and include isActionPending in the disabled/loading guard
consistently with the other header controls.
backend/test/openClawChatBridge.test.ts (1)

385-385: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the retention cap, not just "fewer than the fixture".

toBeLessThan(itemEventCount) passes for any retained count between 0 and 249. A regression that raises or removes the eviction cap still passes the test.

Assert the configured retention limit directly, ideally by importing the constant that the bridge uses.

♻️ Proposed tighter assertion
-        expect(itemToolCount).toBeLessThan(itemEventCount);
+        expect(itemToolCount).toBe(MAX_RETAINED_ITEM_TOOL_EVENTS);

Export the retention limit from the bridge module and import it here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/test/openClawChatBridge.test.ts` at line 385, Update the retention
assertion in openClawChatBridge.test.ts to compare itemToolCount directly
against the bridge’s configured retention-limit constant, rather than only
itemEventCount. Export that retention limit from the bridge module if necessary,
import it in the test, and assert the retained count does not exceed it.
contracts/chatCanonicalUtilities.ts (1)

143-168: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Preserve distinct object keys after key truncation.

Two keys longer than 4096 characters truncate to the same bounded key. The later value then overwrites the earlier value without any marker. A provider key named [truncated] is also overwritten by the truncation marker at Line 146. Diagnostics then show fewer properties than the provider sent.

Disambiguate a bounded key when it already exists.

♻️ Proposed fix to keep truncated keys distinct
         const boundedKey = truncateCanonicalChatText(
             key,
             Math.min(4096, budget.remainingStringCharacters)
         );
+        let uniqueKey = boundedKey;
+        for (let index = 2; uniqueKey in result; index += 1) {
+            uniqueKey = `${boundedKey}#${index}`;
+        }
         budget.remainingStringCharacters = Math.max(
             0,
             budget.remainingStringCharacters - boundedKey.length
         );
         try {
-            result[boundedKey] = boundedCanonicalToolValue(
+            result[uniqueKey] = boundedCanonicalToolValue(
                 item,
                 budget,
                 depth + 1,
                 nestedAncestors
             );
         } catch {
-            result[boundedKey] = "[Unreadable value]";
+            result[uniqueKey] = "[Unreadable value]";
         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/chatCanonicalUtilities.ts` around lines 143 - 168, Update the
object-property handling loop around boundedKey so truncated or
provider-supplied keys cannot overwrite an existing result entry: when the
bounded key already exists, generate a deterministic distinct key before
assigning the value. Preserve the existing "[truncated]" marker behavior while
ensuring a provider key with that name is also disambiguated.
backend/src/gateway.ts (2)

771-781: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the duplicated timestamp validation into one shared helper.

gatewayTimestamp in backend/src/gateway.ts and toTimestamp in backend/src/services/agents.ts implement the same absolute-range timestamp check, including the same 8_640_000_000_000_000 bound. Move this logic into backend/src/lib/values.ts (alongside stringFallback) and import it from both files, so future changes to the validation rule do not need to be applied twice.

  • backend/src/gateway.ts#L771-L781: replace the local gatewayTimestamp function body with a call to the shared helper.
  • backend/src/services/agents.ts#L480-L490: replace the local toTimestamp function body with a call to the shared helper.
♻️ Proposed shared helper
// backend/src/lib/values.ts
export function boundedTimestamp(value: unknown): number | undefined {
    let timestamp = Number.NaN;
    if (typeof value === "number" && Number.isFinite(value)) {
        timestamp = value;
    } else if (typeof value === "string" && value.trim().length > 0) {
        timestamp = Date.parse(value);
    }
    return Number.isFinite(timestamp) && Math.abs(timestamp) <= 8_640_000_000_000_000
        ? timestamp
        : undefined;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/gateway.ts` around lines 771 - 781, Extract the shared timestamp
parsing and absolute-range validation into a new boundedTimestamp helper
alongside stringFallback in backend/src/lib/values.ts. Update
backend/src/gateway.ts lines 771-781 so gatewayTimestamp delegates to
boundedTimestamp, and backend/src/services/agents.ts lines 480-490 so
toTimestamp delegates to it; import the helper in both files and preserve the
documented handling of finite numbers, non-empty strings, and the
8_640_000_000_000_000 bound.

752-853: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Slice raw arrays before mapping, not after, to bound processing cost.

thinkingLevels and thinkingOptions in gatewaySessionFromRecord run .flatMap/.filter/.map over the entire incoming array before .slice(0, 100) truncates the result. If the Gateway (or a compromised/misbehaving connection) sends an array with a very large number of entries, the function still processes every entry before truncating. Since this function exists specifically to bound untrusted Gateway session data, cap the raw array length first.

♻️ Proposed fix to bound processing before mapping
     const thinkingLevels = Array.isArray(record.thinkingLevels)
         ? record.thinkingLevels
+              .slice(0, 1000)
               .flatMap((value) => {
                   const level = asRecord(value);
                   const id = level ? gatewayString(level, "id")?.trim() : undefined;
                   const label = level ? gatewayString(level, "label")?.trim() : undefined;
                   return id && label ? [{ id, label }] : [];
               })
               .slice(0, 100)
         : undefined;
     const thinkingOptions = Array.isArray(record.thinkingOptions)
         ? record.thinkingOptions
+              .slice(0, 1000)
               .filter((value): value is string => typeof value === "string")
               .map((value) => value.trim())
               .filter(Boolean)
               .slice(0, 100)
         : undefined;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/gateway.ts` around lines 752 - 853, Update
gatewaySessionFromRecord so thinkingLevels and thinkingOptions cap their input
arrays to the first 100 elements before flatMap, filter, or map processing.
Preserve the existing validation, trimming, and final output behavior while
ensuring oversized untrusted arrays cannot incur processing beyond the bounded
prefix.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/releaseManifest.ts`:
- Line 39: Ensure MANAGED_DASHBOARD_RUNTIME_LAUNCHER_ARTIFACT is executable
after release staging by either adding an activation test that asserts mode 0755
for the staged launcher or explicitly setting that mode during activation.
Preserve the existing staging behavior for systemd units.

In `@backend/src/services/dockerUpdater.ts`:
- Around line 124-136: Update managedComposePath and its callers to close the
check-use race by opening the validated compose file with a guarded handle,
retaining protection through dirtyDockerUpdaterPaths, fs.readFileSync, and
Docker Compose execution. Revalidate the handle’s regular-file, single-link,
canonical-root, and unchanged-identity properties immediately before reading,
and pass only the protected handle or its trusted path to Compose; ensure
cleanup releases the handle on every path.

In `@backend/src/services/gitHygiene.ts`:
- Around line 104-115: Update gitEnvironment() to delete the inherited
GIT_CONFIG_PARAMETERS entry before assigning GIT_CONFIG_COUNT, GIT_CONFIG_KEY_0,
and GIT_CONFIG_VALUE_0, ensuring Git subprocesses only receive the intended
configuration pairing.

In `@backend/test/serviceBehavior.test.ts`:
- Line 6318: Await the promise-based assertion in the test by updating the
expect(boundedRequest).resolves.toEqual call, ensuring the Bun test runner waits
for the assertion and reports rejections as test failures.

In `@contracts/chatCanonicalMessage.ts`:
- Around line 616-639: Update the array branch around truncateCanonicalChatText
to accumulate normalized blocks incrementally and stop once
MAX_CANONICAL_CHAT_TEXT_CHARACTERS is reached, avoiding an unbounded
map/filter/join intermediate string. Extract the per-item conversion into
canonicalChatTextBlock(item: unknown): string and reuse it for each block,
preserving the existing text, image, and ignored-value mappings.
- Around line 345-364: Update mergeCanonicalChatImages to derive deduplication
identity from the complete image data, including source.data, instead of
summarizeCanonicalChatValueForFingerprint(normalized). Preserve bounded hot-path
fingerprinting while ensuring distinct long base64 payloads with matching edge
samples are not treated as duplicates.

In `@docs/setup/production-deploy.md`:
- Around line 254-266: Update the release readiness comparison in the attempt
loop to require an exact match between current_commit from release-manifest.json
and expected, rather than prefix-matching with expected*. Preserve the existing
retry and failure behavior while enforcing the full SHA contract.

In `@frontend/src/components/features/database/DatabaseSizesTable.tsx`:
- Around line 36-54: Update mergeWithPoolData’s pool metric aggregation to
coerce each current and previous metric value to a finite number before
addition, preventing NaN from propagating through poolMap. Apply this
consistently to cl_active, cl_waiting, sv_active, sv_idle, and sv_used while
preserving the existing stringified sum output and fallback behavior.

In `@frontend/src/pages/Delivery.tsx`:
- Around line 936-944: Update refreshDelivery so refetchPullRequests always runs
even when reconcilePullRequestPreview.mutateAsync fails, while preserving the
existing reconciliation error reporting through setActionError. Use a
finally-style flow around the reconciliation attempt and keep the successful
refresh behavior unchanged.

---

Outside diff comments:
In `@backend/test/chatCanonicalMessage.test.ts`:
- Around line 15-37: Validate provider-supplied attachment URLs in the flow used
by AttachmentPreviewContent and chatImageDisplayUrl before rendering them as img
src or using them for downloads. Accept only data URLs or URLs from trusted
dashboard origins, rejecting arbitrary absolute or untrusted URLs; ensure the
existing canonicalChatImageDisplayUrl and related normalization paths enforce
this contract consistently.

In `@frontend/src/components/features/chat/chatTypes.ts`:
- Around line 297-461: Update chatImageDisplayUrl so data:image/svg+xml URLs
bypass the raster-only isEmbeddedChatImageWithinDimensionLimit check, while PNG,
GIF, JPEG, and WebP continue using it; retain any existing SVG MIME handling and
apply SVG-specific size validation if required. Add a regression test covering
an embedded base64 SVG data URL that successfully passes through
chatImageDisplayUrl.

---

Nitpick comments:
In `@backend/src/gateway.ts`:
- Around line 771-781: Extract the shared timestamp parsing and absolute-range
validation into a new boundedTimestamp helper alongside stringFallback in
backend/src/lib/values.ts. Update backend/src/gateway.ts lines 771-781 so
gatewayTimestamp delegates to boundedTimestamp, and
backend/src/services/agents.ts lines 480-490 so toTimestamp delegates to it;
import the helper in both files and preserve the documented handling of finite
numbers, non-empty strings, and the 8_640_000_000_000_000 bound.
- Around line 752-853: Update gatewaySessionFromRecord so thinkingLevels and
thinkingOptions cap their input arrays to the first 100 elements before flatMap,
filter, or map processing. Preserve the existing validation, trimming, and final
output behavior while ensuring oversized untrusted arrays cannot incur
processing beyond the bounded prefix.

In `@backend/src/services/databaseOverview.ts`:
- Around line 424-442: Update the torrent-count result handling around
countFromResult so rejected Promise.allSettled results are logged with their
rejection reason before returning 0. Preserve the existing fulfilled-result
parsing and zero fallback, and use the surrounding database overview logging
mechanism.

In `@backend/test/openClawChatBridge.test.ts`:
- Line 385: Update the retention assertion in openClawChatBridge.test.ts to
compare itemToolCount directly against the bridge’s configured retention-limit
constant, rather than only itemEventCount. Export that retention limit from the
bridge module if necessary, import it in the test, and assert the retained count
does not exceed it.

In `@contracts/chatCanonicalUtilities.ts`:
- Around line 143-168: Update the object-property handling loop around
boundedKey so truncated or provider-supplied keys cannot overwrite an existing
result entry: when the bounded key already exists, generate a deterministic
distinct key before assigning the value. Preserve the existing "[truncated]"
marker behavior while ensuring a provider key with that name is also
disambiguated.

In `@frontend/src/pages/Delivery.tsx`:
- Around line 1468-1472: Update the Delivery page refresh flow around
RefreshButton and usePullRequests so its loading state remains active while
either reconcilePullRequestPreview is pending or pull-request refetching is in
progress. Destructure and reuse the hook’s isFetching state, and include
isActionPending in the disabled/loading guard consistently with the other header
controls.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0ddd2d1c-0ec1-4e64-b4c1-2af23db63bc2

📥 Commits

Reviewing files that changed from the base of the PR and between a32c67a and 5e313df.

📒 Files selected for processing (71)
  • .github/workflows/codeql.yml
  • .github/workflows/dashboard-checks.yml
  • backend/src/development/developmentOpenClaw.ts
  • backend/src/gateway.ts
  • backend/src/health.ts
  • backend/src/http.ts
  • backend/src/lib/logTail.ts
  • backend/src/lib/openclawGatewayClient.ts
  • backend/src/lib/values.ts
  • backend/src/managedDashboardUnitPolicy.ts
  • backend/src/releaseDeployment.ts
  • backend/src/releaseManifest.ts
  • backend/src/requestPolicy.ts
  • backend/src/routes/cacheRoutes.ts
  • backend/src/routes/cronRoutes.ts
  • backend/src/routes/openclawConfigRoutes.ts
  • backend/src/routes/pullRequestRoutes.ts
  • backend/src/routes/taskRoutes.ts
  • backend/src/services/agents.ts
  • backend/src/services/backups.ts
  • backend/src/services/cacheRefresh.ts
  • backend/src/services/databaseOverview.ts
  • backend/src/services/dockerUpdater.ts
  • backend/src/services/gitHygiene.ts
  • backend/src/services/pullRequests.ts
  • backend/src/services/quotaNotifications.ts
  • backend/test/chatCanonicalMessage.test.ts
  • backend/test/databaseOverview.test.ts
  • backend/test/developmentStack.test.ts
  • backend/test/dockerUpdater.test.ts
  • backend/test/gatewayBehavior.test.ts
  • backend/test/gitHygiene.test.ts
  • backend/test/healthReadiness.test.ts
  • backend/test/httpApiBehavior.test.ts
  • backend/test/httpCookieBehavior.test.ts
  • backend/test/openClawChatBridge.test.ts
  • backend/test/releaseDeployment.test.ts
  • backend/test/releaseManager.test.ts
  • backend/test/releaseManifest.test.ts
  • backend/test/routeAndServiceBehavior.test.ts
  • backend/test/serviceBehavior.test.ts
  • backend/test/support/releaseFixture.ts
  • backend/test/utilityBehavior.test.ts
  • contracts/chat/openClawAdapterValues.ts
  • contracts/chat/openClawHistoryNormalizer.ts
  • contracts/chat/openClawToolAdapter.ts
  • contracts/chatCanonicalMessage.ts
  • contracts/chatCanonicalUtilities.ts
  • contracts/health.ts
  • contracts/socket.ts
  • docs/setup/production-deploy.md
  • frontend/src/collections/logs.ts
  • frontend/src/components/features/chat/chatPageUtilities.ts
  • frontend/src/components/features/chat/chatTypes.ts
  • frontend/src/components/features/chat/chatUtilities.ts
  • frontend/src/components/features/chat/domain/chatState.ts
  • frontend/src/components/features/database/DatabaseSizesTable.tsx
  • frontend/src/components/ui/Button.tsx
  • frontend/src/hooks/index.ts
  • frontend/src/hooks/useCron.ts
  • frontend/src/hooks/useDelivery.ts
  • frontend/src/hooks/useFileExplorerState.ts
  • frontend/src/pages/Delivery.tsx
  • frontend/src/test/chatCanonicalProjection.test.ts
  • frontend/src/test/chatState.test.ts
  • frontend/src/test/componentBehavior.test.tsx
  • frontend/src/test/frontendBehavior.test.tsx
  • frontend/src/test/openClawAdapterVariants.test.ts
  • frontend/src/test/pageBehavior.test.tsx
  • systemd/mira-dashboard-worker.service
  • systemd/mira-dashboard.service
💤 Files with no reviewable changes (2)
  • backend/src/health.ts
  • contracts/health.ts
📜 Review details
🧰 Additional context used
🪛 OpenGrep (1.26.0)
frontend/src/components/features/chat/chatTypes.ts

[ERROR] 303-303: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

contracts/chatCanonicalMessage.ts

[ERROR] 367-367: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🔇 Additional comments (76)
backend/test/developmentStack.test.ts (1)

330-343: LGTM!

backend/test/dockerUpdater.test.ts (2)

2-9: LGTM!


255-295: LGTM!

backend/src/lib/logTail.ts (1)

13-14: LGTM!

Also applies to: 87-87, 105-118

backend/src/http.ts (1)

267-273: LGTM!

Also applies to: 275-310, 312-347

backend/src/requestPolicy.ts (1)

627-639: LGTM!

backend/src/routes/cacheRoutes.ts (1)

48-55: LGTM!

Also applies to: 67-74, 123-130, 164-172, 233-239

backend/src/routes/pullRequestRoutes.ts (1)

81-81: LGTM!

Also applies to: 263-278

backend/src/routes/taskRoutes.ts (1)

23-23: LGTM!

Also applies to: 306-328

backend/src/services/backups.ts (1)

1171-1186: LGTM!

backend/src/services/quotaNotifications.ts (1)

185-186: LGTM!

backend/test/routeAndServiceBehavior.test.ts (1)

29-29: LGTM!

Also applies to: 1002-1042, 3245-3254, 3650-3653, 5306-5327, 5645-5652, 5683-5685

backend/test/httpCookieBehavior.test.ts (1)

5-10: LGTM!

Also applies to: 36-48

backend/test/httpApiBehavior.test.ts (1)

378-380: 🎯 Functional Correctness

No change needed.

The unauthenticatedApi type literal has a single checks declaration, so there is no duplicate property error to address.

			> Likely an incorrect or invalid review comment.
backend/src/services/cacheRefresh.ts (4)

1-3: LGTM!


1399-1435: LGTM!


1512-1512: LGTM!

Also applies to: 1526-1526, 1539-1579


2324-2340: LGTM!

backend/src/services/databaseOverview.ts (1)

444-450: LGTM!

Also applies to: 543-547, 658-660

backend/test/utilityBehavior.test.ts (1)

474-488: LGTM!

Also applies to: 587-587, 1354-1377, 1489-1489

backend/test/databaseOverview.test.ts (1)

263-266: LGTM!

Also applies to: 313-318

backend/test/healthReadiness.test.ts (1)

49-50: LGTM!

frontend/src/hooks/index.ts (1)

70-70: LGTM!

frontend/src/hooks/useCron.ts (1)

49-56: LGTM!

Also applies to: 73-79, 95-98, 114-117

frontend/src/hooks/useDelivery.ts (1)

243-248: LGTM!

Also applies to: 318-332

frontend/src/pages/Delivery.tsx (1)

53-53: LGTM!

Also applies to: 709-718, 889-889, 902-903

frontend/src/test/frontendBehavior.test.tsx (2)

48-48: LGTM!

Also applies to: 3462-3481, 4695-4700, 4736-4736, 6217-6229, 6487-6505


6617-6628: 🎯 Functional Correctness

No change needed. This PNG branch only checks the first four PNG bytes and reads the widths at offsets 16 and 20, so the remaining zero signature bytes do not prevent the oversized-width assertion from exercising the dimension parser.

			> Likely an incorrect or invalid review comment.
contracts/chatCanonicalUtilities.ts (1)

43-76: LGTM!

Also applies to: 176-186

contracts/chatCanonicalMessage.ts (1)

7-11: LGTM!

Also applies to: 69-80, 215-215, 235-235, 366-421, 498-516, 546-549, 578-584

contracts/chat/openClawAdapterValues.ts (1)

4-8: LGTM!

Also applies to: 54-75

contracts/chat/openClawHistoryNormalizer.ts (1)

18-22: LGTM!

Also applies to: 381-384

contracts/chat/openClawToolAdapter.ts (2)

6-11: LGTM!

Also applies to: 115-118


75-77: 🗄️ Data Integrity & Integration

No change needed for id-less tool IDs.

stableCanonicalChatStringify does not apply node/string budgets before keying; budget truncation has already replaced oversized arguments_. Duplicates are handled by occurrence keys later, so this does not merge distinct id-less tool rows.

			> Likely an incorrect or invalid review comment.
backend/test/chatCanonicalMessage.test.ts (1)

9-12: LGTM!

Also applies to: 62-63, 81-132

backend/test/openClawChatBridge.test.ts (1)

8-8: LGTM!

Also applies to: 350-351, 1796-1796, 1828-1838

frontend/src/test/openClawAdapterVariants.test.ts (1)

1496-1496: LGTM!

frontend/src/test/componentBehavior.test.tsx (1)

536-536: LGTM!

Also applies to: 4781-4804, 4821-4821

frontend/src/test/pageBehavior.test.tsx (1)

5652-5665: LGTM!

frontend/src/collections/logs.ts (1)

7-9: LGTM!

Also applies to: 61-72

frontend/src/components/features/chat/chatPageUtilities.ts (1)

27-36: LGTM!

Also applies to: 46-66, 92-95

frontend/src/components/features/chat/chatTypes.ts (1)

6-10: LGTM!

Also applies to: 20-22, 264-295, 506-506, 689-689

frontend/src/components/features/chat/chatUtilities.ts (1)

785-785: LGTM!

frontend/src/components/features/chat/domain/chatState.ts (1)

5-9: LGTM!

Also applies to: 29-29, 754-798, 812-815

frontend/src/components/ui/Button.tsx (1)

30-30: LGTM!

frontend/src/hooks/useFileExplorerState.ts (1)

9-9: LGTM!

frontend/src/test/chatCanonicalProjection.test.ts (1)

918-921: LGTM!

Also applies to: 1001-1009, 1119-1132

frontend/src/test/chatState.test.ts (1)

3-11: LGTM!

Also applies to: 820-869

.github/workflows/codeql.yml (1)

27-37: LGTM!

.github/workflows/dashboard-checks.yml (1)

25-30: LGTM!

Also applies to: 50-50, 59-59, 78-83, 101-101, 110-110

backend/src/managedDashboardUnitPolicy.ts (1)

16-17: LGTM!

backend/src/releaseDeployment.ts (1)

19-19: LGTM!

Also applies to: 258-260

backend/src/releaseManifest.ts (1)

22-25: LGTM!

systemd/mira-dashboard-worker.service (1)

12-12: LGTM!

backend/test/releaseDeployment.test.ts (1)

148-148: LGTM!

Also applies to: 173-173

backend/test/releaseManifest.test.ts (1)

69-76: LGTM!

Also applies to: 225-225

backend/src/lib/values.ts (1)

43-44: LGTM!

backend/src/services/pullRequests.ts (1)

189-190: LGTM!

Also applies to: 1045-1045, 1927-1927, 1944-1953, 3010-3015, 4271-4296

systemd/mira-dashboard.service (1)

12-12: LGTM!

backend/test/releaseManager.test.ts (1)

154-161: LGTM!

backend/test/support/releaseFixture.ts (1)

33-40: LGTM!

backend/test/serviceBehavior.test.ts (1)

206-208: LGTM!

Also applies to: 243-249, 713-715, 1031-1033, 2863-2863, 3413-3413, 3572-3576, 5365-5365, 8483-8487, 8962-8967, 8980-8989, 9079-9082

backend/src/services/dockerUpdater.ts (1)

89-102: LGTM!

Also applies to: 571-585, 1687-1692, 1728-1728, 1765-1769, 1851-1852, 1892-1900, 2859-2860

backend/src/services/gitHygiene.ts (1)

34-34: LGTM!

Also applies to: 243-243, 299-299, 531-532

backend/src/gateway.ts (1)

10-10: LGTM!

Also applies to: 47-48, 862-880, 919-924, 1307-1313

backend/src/lib/openclawGatewayClient.ts (2)

24-38: LGTM!

Also applies to: 742-756


126-127: 🩺 Stability & Availability

No remaining shouldWaitIndefinitely usage left.

contracts/socket.ts (1)

14-23: LGTM!

backend/src/services/agents.ts (1)

1587-1587: LGTM!

backend/test/gatewayBehavior.test.ts (1)

342-363: LGTM!

Also applies to: 1060-1060

backend/src/routes/openclawConfigRoutes.ts (2)

96-129: LGTM!


131-144: 🎯 Functional Correctness

Confirm hard-linked SKILL.md files are not a realistic packaging pattern.

isBoundedSkillManifest requires nlink === 1, so any SKILL.md with more than one hard link is excluded and drops the entire skill from /api/skills when collectSkillDirectories() filters out the directory. If OpenClaw skill installation or package tooling can create hard-linked manifests, change the check or raise a visible error instead of silently skipping valid skills.

backend/src/routes/cronRoutes.ts (2)

112-126: LGTM!

Also applies to: 139-144, 156-157, 169-169, 183-184, 195-198


33-59: 📐 Maintainability & Code Quality

No change needed. backend/src/routes/taskRoutes.ts defines cronJobId(job: CronJob), which is not the same parameter-validation function as cronJobId(request).

			> Likely an incorrect or invalid review comment.
backend/src/development/developmentOpenClaw.ts (1)

75-76: LGTM!

backend/test/gitHygiene.test.ts (1)

104-112: LGTM!

Comment thread backend/src/releaseManifest.ts
Comment thread backend/src/services/dockerUpdater.ts
Comment thread backend/src/services/gitHygiene.ts
Comment thread backend/test/serviceBehavior.test.ts Outdated
Comment thread contracts/chatCanonicalMessage.ts
Comment thread contracts/chatCanonicalMessage.ts Outdated
Comment thread docs/setup/production-deploy.md Outdated
Comment thread frontend/src/components/features/database/DatabaseSizesTable.tsx
Comment thread frontend/src/pages/Delivery.tsx Outdated
@mira-2026

mira-2026 commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Review follow-up (fe219d77)

All CodeRabbit feedback, including outside-diff comments and nitpicks, was validated against the current implementation.

Outside-diff comments

  • Provider attachment URLs: No code change. Arbitrary external HTTP(S) URLs are rejected as image sources by chatImageDisplayUrl; they remain click-only links. Managed/local Dashboard media URLs remain previewable.
  • Embedded SVG data URLs: No code change by design. Inline provider data:image/svg+xml content is intentionally outside the embedded raster allowlist. Managed Dashboard SVG URLs continue to work in Attachment Preview, preserving the feature without weakening the XSS boundary.

Nitpicks addressed

  • Rejected optional torrent-count probes now emit structured warnings.
  • Manual Delivery refresh now shows loading for the full reconcile-plus-refetch lifecycle; background polling remains unchanged.
  • Replay retention coverage now asserts the aggregate byte cap.
  • Bounded tool-object keys and the truncation marker remain unique after truncation.
  • Shared Date-safe timestamp validation replaces duplicate implementations.
  • Raw thinking-level and thinking-option arrays are capped before mapping/filtering.

Validation

  • Frontend: 665 tests passed, 0 failed (4,354 assertions).
  • Backend: 711 tests passed, 0 failed (4,559 assertions).
  • Formatting, lint, frontend build, backend build, and diff checks passed.
  • Frontend coverage was expanded across GIF, JPEG, WebP variants, malformed embedded data, and Delivery refresh failure behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/releaseManager.ts`:
- Around line 1239-1241: Update publishVerifiedDashboardRelease() so the
existing-release path repairs the execute bit on
scripts/runManagedDashboardRelease.sh before returning
loadManagedReleaseFromLayout(). Reuse the existing
MANAGED_DASHBOARD_RUNTIME_LAUNCHER_ARTIFACT and destination-path chmod behavior,
making the check idempotent while preserving the existing loader validation and
return flow.

In `@backend/src/services/agents.ts`:
- Line 1545: Update the session guard around boundedTimestamp so it explicitly
checks whether the returned endedAt value is undefined, preserving 0 as a valid
epoch timestamp and preventing such sessions from remaining marked as running.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f091fa90-4ae7-423c-b280-f570816d866d

📥 Commits

Reviewing files that changed from the base of the PR and between 5e313df and fe219d7.

📒 Files selected for processing (21)
  • backend/src/gateway.ts
  • backend/src/lib/values.ts
  • backend/src/releaseManager.ts
  • backend/src/services/agents.ts
  • backend/src/services/databaseOverview.ts
  • backend/src/services/gitHygiene.ts
  • backend/test/chatCanonicalMessage.test.ts
  • backend/test/gatewayBehavior.test.ts
  • backend/test/gitHygiene.test.ts
  • backend/test/openClawChatBridge.test.ts
  • backend/test/releaseManager.test.ts
  • backend/test/serviceBehavior.test.ts
  • backend/test/utilityBehavior.test.ts
  • contracts/chatCanonicalMessage.ts
  • contracts/chatCanonicalUtilities.ts
  • docs/setup/production-deploy.md
  • frontend/src/components/features/database/DatabaseSizesTable.tsx
  • frontend/src/pages/Delivery.tsx
  • frontend/src/test/componentBehavior.test.tsx
  • frontend/src/test/frontendBehavior.test.tsx
  • frontend/src/test/pageBehavior.test.tsx
🚧 Files skipped from review as they are similar to previous changes (15)
  • backend/test/gitHygiene.test.ts
  • backend/src/services/gitHygiene.ts
  • backend/test/openClawChatBridge.test.ts
  • backend/src/gateway.ts
  • backend/test/utilityBehavior.test.ts
  • docs/setup/production-deploy.md
  • backend/test/serviceBehavior.test.ts
  • contracts/chatCanonicalMessage.ts
  • frontend/src/test/componentBehavior.test.tsx
  • frontend/src/pages/Delivery.tsx
  • backend/test/gatewayBehavior.test.ts
  • contracts/chatCanonicalUtilities.ts
  • frontend/src/components/features/database/DatabaseSizesTable.tsx
  • frontend/src/test/frontendBehavior.test.tsx
  • backend/test/releaseManager.test.ts
📜 Review details
🔇 Additional comments (10)
backend/test/chatCanonicalMessage.test.ts (1)

11-18: LGTM!

Also applies to: 21-43, 69-69, 87-138, 140-197

frontend/src/test/pageBehavior.test.tsx (2)

5696-5709: 📐 Maintainability & Code Quality

No change needed. The existing assertions cover malformed storage clearing, legacy prompt-text cleanup, and opaque key rewriting.


3217-3242: 📐 Maintainability & Code Quality

No fetch cleanup issue remains.

The suite beforeEach resets globalThis.fetch before each test, and afterEach restores originalGlobals.fetch, so this local mock cannot leak into the next test.

backend/src/releaseManager.ts (1)

27-27: LGTM!

backend/src/services/agents.ts (1)

25-25: LGTM!

Also applies to: 475-475, 1510-1511, 1568-1570

backend/src/lib/values.ts (2)

138-154: LGTM!


43-44: 🎯 Functional Correctness

No caller changes needed.

backend/src/services/databaseOverview.ts (3)

10-10: LGTM!

Also applies to: 24-24


430-444: LGTM!


551-555: 🎯 Functional Correctness

Threshold rules are aligned.

Comment thread backend/src/releaseManager.ts
Comment thread backend/src/services/agents.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 18e8c6bba6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/routes/pullRequestRoutes.ts
Comment thread backend/src/services/pullRequests.ts
Comment thread contracts/chatCanonicalMessage.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/releaseManager.ts`:
- Around line 1222-1239: Extract the existing launcher chmod operation into an
ensureManagedLauncherExecutable helper, and call it for both existingRelease and
concurrentlyPublished paths. Update the EEXIST/ENOTEMPTY collision branch to
repair concurrentlyPublished before returning it, preserving the current
release-return behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 828d2d57-96f6-497a-a1f6-61b1a589cc6b

📥 Commits

Reviewing files that changed from the base of the PR and between fe219d7 and c884b0c.

📒 Files selected for processing (24)
  • backend/src/database.ts
  • backend/src/gatewayToken.ts
  • backend/src/releaseManager.ts
  • backend/src/routes/mediaRoutes.ts
  • backend/src/routes/pullRequestRoutes.ts
  • backend/src/serverStart.ts
  • backend/src/services/agents.ts
  • backend/src/services/pullRequestPreviewHost.ts
  • backend/src/services/pullRequestPreviews.ts
  • backend/src/services/pullRequests.ts
  • backend/test/chatCanonicalMessage.test.ts
  • backend/test/gatewayBehavior.test.ts
  • backend/test/pullRequestPreview.test.ts
  • backend/test/releaseManager.test.ts
  • backend/test/serverStartupPolicy.test.ts
  • backend/test/serviceBehavior.test.ts
  • backend/test/testDatabaseGuard.test.ts
  • contracts/chat/openClawHistoryNormalizer.ts
  • contracts/chat/openClawHistoryPageAdapter.ts
  • contracts/chatCanonical.ts
  • contracts/chatCanonicalMessage.ts
  • frontend/src/pages/Delivery.tsx
  • frontend/src/test/pageBehavior.test.tsx
  • package.json
💤 Files with no reviewable changes (2)
  • frontend/src/test/pageBehavior.test.tsx
  • backend/src/routes/pullRequestRoutes.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • frontend/src/pages/Delivery.tsx
  • backend/test/gatewayBehavior.test.ts
  • backend/test/chatCanonicalMessage.test.ts
  • backend/src/services/agents.ts
  • backend/src/services/pullRequests.ts
  • contracts/chatCanonicalMessage.ts
  • backend/test/serviceBehavior.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: backend-checks
🔇 Additional comments (23)
backend/src/releaseManager.ts (1)

550-597: LGTM!

Also applies to: 886-911, 1273-1275

backend/src/database.ts (1)

21-37: LGTM!

Also applies to: 51-60, 99-99, 284-284, 308-308

backend/src/gatewayToken.ts (1)

1-18: LGTM!

backend/src/routes/mediaRoutes.ts (1)

6-6: LGTM!

Also applies to: 85-87

backend/src/serverStart.ts (1)

2-2: LGTM!

backend/src/services/pullRequestPreviewHost.ts (1)

31-31: LGTM!

Also applies to: 1706-1709

backend/src/services/pullRequestPreviews.ts (3)

6-6: LGTM!

Also applies to: 31-36, 46-47


245-276: LGTM!


371-379: LGTM!

Also applies to: 437-467

contracts/chatCanonical.ts (1)

8-17: LGTM!

Also applies to: 31-31

contracts/chat/openClawHistoryNormalizer.ts (3)

12-12: LGTM!


369-387: LGTM!


415-440: LGTM!

contracts/chat/openClawHistoryPageAdapter.ts (3)

1-4: LGTM!


57-67: LGTM!


99-108: LGTM!

package.json (1)

15-16: LGTM!

backend/test/pullRequestPreview.test.ts (3)

527-528: 🩺 Stability & Availability

Verify token restoration runs even if an earlier assertion fails.

The lifecycle test sets OPENCLAW_GATEWAY_TOKEN at line 528, switches expectedUpstreamToken at line 771-772, and restores the original value at lines 1031-1035. This span covers many assertions between the mutation and the restoration.

If an assertion between line 528 and line 1031 throws, the restoration step does not run. The modified environment variable then leaks into later tests in the same process, causing unrelated test failures or flaky passes.

Confirm that this restoration executes inside a try/finally block or an afterEach hook. If it does not, wrap the token mutation and restoration in try/finally.

Also applies to: 543-543, 632-632, 771-772, 1031-1035


1344-1373: LGTM!


1283-1289: 🎯 Functional Correctness

No change needed for these .resolves/.rejects matchers.

Bun’s native test matchers do not require await on the assertion expression; adding await here is optional style, not a functional fix.

			> Likely an incorrect or invalid review comment.
backend/test/releaseManager.test.ts (1)

365-390: LGTM!

Also applies to: 521-547

backend/test/serverStartupPolicy.test.ts (1)

70-72: LGTM!

backend/test/testDatabaseGuard.test.ts (1)

1-1: LGTM!

Also applies to: 104-139, 184-226

Comment thread backend/src/releaseManager.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 00b173ae57

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread backend/src/releaseManifest.ts
Comment thread backend/src/services/pullRequests.ts
Comment thread backend/src/releaseDeployment.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 96df63c23e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread package.json Outdated
@mira-2026
mira-2026 merged commit 30fca6d into main Aug 1, 2026
7 checks passed
@mira-2026
mira-2026 deleted the mira/security-scan-hardening-2026-07-31 branch August 1, 2026 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: backend Backend API, server routes, services, and integrations area: ci CI, test runners, workflow checks, and release gates area: frontend Frontend UI, client state, routing, and browser behavior area: ops Operational actions, deploys, services, backups, and health priority: high High-priority work for the next active cycle status: needs-review Ready for human or agent review type: security Security, auth, secrets, or trust-boundary work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants