Skip to content

Complete atomic Dashboard release cutover - #334

Merged
mira-2026 merged 11 commits into
mainfrom
atomic-release-cutover
Jul 26, 2026
Merged

Complete atomic Dashboard release cutover#334
mira-2026 merged 11 commits into
mainfrom
atomic-release-cutover

Conversation

@mira-2026

@mira-2026 mira-2026 commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • build each exact deployment commit in an isolated detached worktree and publish only manifest-declared artifacts to an immutable release directory
  • switch current/previous atomically, restart web and worker together, require commit-bound readiness, and automatically roll back on failure
  • retain the current, previous, and one additional verified release while safely pruning older releases
  • move production SQLite, backups, Dashboard Gateway identity, and log-rotation locking to /home/ubuntu/projects/mira-dashboard-state
  • remove release-manifest format 1 and legacy /health//api/health compatibility
  • add the controlled one-time production cutover and recovery runbook

Behavior and regression coverage

  • deployments stage and verify an immutable SHA release before any production link changes
  • failed activation or commit-bound readiness rolls back web and worker to the verified previous release
  • orphan reconciliation preserves a healthy candidate that is already active, while failed or stale cutovers still enter recovery
  • one-time cutover readiness requires a stable worker systemd identity beyond the heartbeat freshness window
  • manual rollback executes the verified previous release lifecycle binary
  • production state and backups remain outside immutable release directories
  • release, cutover, retention, state-path, health-route, systemd, worker-queue, and recovery regressions are covered by automated tests

Verification

  • Frontend lint: bun run lint:frontend
  • Frontend build: bun run build
  • Frontend tests/coverage: bun run test:coverage (465 tests, 94.42% lines)
  • Backend lint: bun run lint:backend
  • Backend build: bun run build from backend/
  • Backend tests/coverage: bun run test:coverage from backend/ (544 tests, 90.13% lines)
  • Focused regression tests: release deployment/manager, service behavior, and job execution queue suites
  • Manual UI/API smoke check: deferred to the documented one-time managed cutover after merge
  • Codecov backend patch: 89.75721% (target 85%)
  • CodeQL and managed systemd unit verification
  • Fresh-state deploy:prepare: database initialization, restore-verified backup, schema preflight, build, and format-2 manifest verification (33 artifacts)
  • OpenClaw/runtime path audit found no consumer of removed production paths or legacy health routes

Risk checklist

  • No secrets, tokens, .env files, database dumps, or runtime state committed
  • Auth, Gateway, terminal, file, Docker, and settings boundaries were reviewed; no auth contract is broadened
  • Removed health aliases have no remaining OpenClaw or production consumer
  • Database/state relocation includes a controlled move, backup verification, preflight, and rollback runbook
  • Runtime/reconnect behavior preserves deployment ordering, idempotency, worker ownership, and orphan recovery
  • The visible header change is limited to the two-letter WK worker status badge beside WS and BE

Deployment / operations

  • No deploy/restart needed
  • Deploy/restart needed after merge: perform the documented one-time managed cutover for mira-dashboard.service and mira-dashboard-worker.service
  • Config/secrets changes needed: no secret rotation; install the managed unit definitions and persistent state-root paths during cutover
  • Rollback path verified: retain PR Add immutable atomic release manager #333 as the bootstrap/previous release and use automatic rollback or the verified previous lifecycle binary

This PR must not be deployed with the pre-cutover executor. After merge, use the documented one-time managed cutover to:

  1. stage PR Add immutable atomic release manager #333 as the known-good bootstrap plus this candidate,
  2. stop both units,
  3. atomically move persistent state,
  4. install the managed units,
  5. verify bootstrap and candidate readiness,
  6. retain automatic rollback to the bootstrap.

No production cutover is performed by this PR itself.

Notes for reviewers

  • focus on activation/rollback ordering, persistent state separation, orphan recovery, and the one-time cutover runbook
  • release-manifest format 1 and legacy health aliases are intentionally removed; this is a single-consumer Dashboard with audited callers
  • closes the final implementation wave of Task feat: start greenfield Dashboard rewrite foundation #378

@mira-2026
mira-2026 requested a review from rajohan as a code owner July 26, 2026 03:20
@mira-2026 mira-2026 added priority: high High-priority work for the next active cycle status: needs-review Ready for human or agent review status: do-not-merge Must not be merged until explicitly cleared type: feature Adds user-visible functionality area: ops Operational actions, deploys, services, backups, and health area: backend Backend API, server routes, services, and integrations labels Jul 26, 2026
@coderabbitai

coderabbitai Bot commented Jul 26, 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: 59 seconds

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: a6de53ca-2f84-40be-831c-52c7ae035ee3

📥 Commits

Reviewing files that changed from the base of the PR and between 178686d and 2323736.

📒 Files selected for processing (16)
  • backend/src/releaseManager.ts
  • backend/src/routes/configFileRoutes.ts
  • backend/src/routes/fileRoutes.ts
  • backend/src/routes/mediaRoutes.ts
  • backend/src/routes/openclawConfigRoutes.ts
  • backend/src/services/agents.ts
  • backend/src/services/gitHygiene.ts
  • backend/src/services/pullRequests.ts
  • backend/src/services/scheduledJobs.ts
  • backend/test/gitHygiene.test.ts
  • backend/test/jobExecutionQueue.test.ts
  • backend/test/releaseManager.test.ts
  • backend/test/routeAndServiceBehavior.test.ts
  • backend/test/serviceBehavior.test.ts
  • docs/setup/production-deploy.md
  • docs/setup/secrets-and-env.md
📝 Walkthrough

Walkthrough

The PR adds immutable dashboard release staging, atomic cutover and rollback, release retention pruning, format-2 manifest enforcement, managed systemd validation, orphaned-cutover reconciliation, health-route changes, configurable log-rotation paths, and related tests and documentation.

Changes

Managed release platform

Layer / File(s) Summary
Release and runtime contracts
backend/src/releaseManifest.ts, backend/src/releaseDeployment.ts, backend/src/routes.ts, backend/src/requestPolicy.ts, backend/src/lib/*, backend/src/server.ts, backend/test/*
Release manifests require format 2 and migration inventory identities; runtime paths, ports, health routes, and managed service properties use centralized validation and updated contracts.
Verified release staging and publication
backend/src/releaseDeployment.ts, backend/src/releaseManager.ts, backend/test/releaseDeployment.test.ts, backend/test/support/releaseFixture.ts
Detached worktrees build and verify releases before atomic SHA-based publication, with immutable reuse, concurrency handling, cleanup fallbacks, CLI dispatch, and fixture coverage.
Retention pruning and lifecycle commands
backend/src/releaseManager.ts, backend/src/releaseLifecycle.ts, backend/test/releaseManager.test.ts
Managed releases are pruned under transition locking while protecting current and previous releases; lifecycle commands expose retention cleanup and validate retention arguments.
Deployment orchestration and atomic cutover
backend/src/services/pullRequests.ts, backend/test/serviceBehavior.test.ts
Deployment jobs validate managed units, stage candidates, schedule detached activation, verify commit-bound readiness, prune successful releases, and roll back failed activations.
Deployment guardian reconciliation
backend/src/services/scheduledJobs.ts, backend/src/services/jobExecutionQueue.ts, backend/test/jobExecutionQueue.test.ts
Scheduler reconciliation inspects guardian and recovery units, invokes recovery for orphaned cutovers, and prevents replacement workers from claiming pending deployment jobs.
Log rotation and production operations
backend/src/services/logRotation.ts, backend/package.json, systemd/*, docs/*
Configured persistent-state paths, managed release workspaces, explicit environment preservation, log-rotation lock identity checks, deployment procedures, database runbooks, and readiness documentation are updated.

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

Possibly related PRs

Suggested labels: area: database, area: frontend

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: an atomic Dashboard release cutover.
Description check ✅ Passed The description follows the repository template and covers summary, behavior, verification, risk, deployment, and reviewer notes.
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.

@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.29475% with 135 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/src/releaseDeployment.ts 84.39% 61 Missing ⚠️
backend/src/releaseManager.ts 85.17% 51 Missing ⚠️
backend/src/services/pullRequests.ts 93.41% 22 Missing ⚠️
backend/src/server.ts 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@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: b81e27c689

ℹ️ 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 systemd/mira-dashboard.service Outdated
Comment thread backend/src/services/pullRequests.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: 6

🧹 Nitpick comments (6)
backend/src/services/logRotation.ts (1)

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

Duplicate absolute/non-root path validator.

This is the same rule as resolveAbsoluteNonRootPath in backend/src/releaseDeployment.ts (lines 80-90), minus the trim()-before-isAbsolute ordering. Two copies of a security-relevant validator will drift; extract one shared helper (e.g. into lib/) and have both call it. Minor nit alongside: path.resolve(configured) is recomputed three times.

♻️ Sketch
 function resolveLogRotationLockFile(): string {
-    const configured =
-        process.env.MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE?.trim() || DEFAULT_LOCK_FILE;
-    if (
-        configured.includes("\0") ||
-        !path.isAbsolute(configured) ||
-        path.resolve(configured) === path.parse(path.resolve(configured)).root
-    ) {
-        throw new TypeError(
-            "MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE must be an absolute non-root path"
-        );
-    }
-    return path.resolve(configured);
+    return resolveAbsoluteNonRootPath(
+        process.env.MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE?.trim() || DEFAULT_LOCK_FILE,
+        "MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE"
+    );
 }
🤖 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/logRotation.ts` around lines 71 - 86, Extract the
absolute, non-root path validation from resolveLogRotationLockFile and
resolveAbsoluteNonRootPath into one shared helper, preserving trimming,
null-byte rejection, absolute-path enforcement, and non-root rejection. Update
both callers to use the shared helper and reuse a single resolved-path
computation within it instead of repeatedly calling path.resolve.
systemd/mira-dashboard-worker.service (1)

9-18: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Managed-path contract is hand-duplicated across both unit files with no single source of truth. assertManagedDashboardUnitProperties requires exact string equality against managedDashboardUnitContract(), yet the same six paths are maintained independently in two unit files and again as DEFAULT_DASHBOARD_* constants in backend/src/releaseDeployment.ts. A single typo in any copy fails the contract gate and blocks every deployment, and there is no test asserting the shipped unit files satisfy the contract.

  • systemd/mira-dashboard-worker.service#L9-L18: verify WorkingDirectory and all five Environment= values match managedDashboardUnitContract() exactly, and add a unit test that feeds this file's parsed properties into assertManagedDashboardUnitProperties("mira-dashboard-worker.service", …).
  • systemd/mira-dashboard.service#L9-L18: apply the identical verification and add the equivalent assertion for "mira-dashboard.service", so drift in either file is caught in CI rather than at deploy time.
🤖 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 `@systemd/mira-dashboard-worker.service` around lines 9 - 18, Verify
WorkingDirectory and all five Environment values in
systemd/mira-dashboard-worker.service lines 9-18 against
managedDashboardUnitContract(), then add a unit test parsing that file and
passing its properties to
assertManagedDashboardUnitProperties("mira-dashboard-worker.service", …). Apply
the same verification and equivalent assertion for
systemd/mira-dashboard.service lines 9-18 using "mira-dashboard.service",
ensuring both shipped unit files are covered by CI.
backend/test/releaseDeployment.test.ts (1)

254-307: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Concurrency test can hang instead of failing.

buildsReleased only resolves when deploy:prepare is reached twice. If either staging run fails earlier (or short-circuits via release reuse), the other awaits forever and the test hangs until the suite timeout, with no useful diagnostic. Consider racing the barrier with a bounded timeout.

♻️ Bounded barrier
-                buildsReady += 1;
-                if (buildsReady === 2) {
-                    releaseBuilds();
-                }
-                await buildsReleased;
+                buildsReady += 1;
+                if (buildsReady === 2) {
+                    releaseBuilds();
+                }
+                await Promise.race([
+                    buildsReleased,
+                    Bun.sleep(5000).then(() => {
+                        throw new Error("concurrent build barrier timed out");
+                    }),
+                ]);
🤖 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/releaseDeployment.test.ts` around lines 254 - 307, Make the
concurrency barrier in the “accepts a concurrently published copy of the same
verified release” test bounded so buildsReleased cannot wait indefinitely if
either stageDashboardRelease call exits early or fails. Race the deploy:prepare
synchronization wait against a short timeout, while preserving the existing
two-build coordination and shared-path assertions.
backend/test/serviceBehavior.test.ts (1)

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

Release fixture is duplicated across test files.

createDeploymentReleaseFixture is near-identical to createBuiltRelease in backend/test/releaseDeployment.test.ts (same directory tree, lockfiles, build-identity payloads, entrypoint list, manifest write). Extracting a shared helper (e.g. backend/test/support/releaseFixture.ts) keeps the artifact contract in one place as the manifest format evolves.

🤖 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/serviceBehavior.test.ts` around lines 50 - 109, Extract
createDeploymentReleaseFixture and the shared release-artifact setup into a
reusable helper under the test support area, then update serviceBehavior.test.ts
and releaseDeployment.test.ts to use it. Preserve the existing directory tree,
lockfiles, build-identity payloads, entrypoint list, and writeReleaseManifest
inputs so both tests continue validating the same release contract from one
implementation.
backend/src/releaseManager.ts (2)

1257-1262: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Retention ordering falls back to commit SHA when builtAt ties, and the tests bake that in. Sorting compares ISO builtAt with localeCompare and breaks ties by descending SHA, which is unrelated to recency; the prune test creates all fixtures with the same builtAt, so it validates the tie-break rather than newest-first retention.

  • backend/src/releaseManager.ts#L1257-L1262: compare builtAt with plain </> and pick a meaningful tie-break (e.g. directory birth time) instead of SHA order.
  • backend/test/releaseManager.test.ts#L830-L851: give each managed release fixture a distinct builtAt so the retained ordering assertion exercises recency.
🤖 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/releaseManager.ts` around lines 1257 - 1262, Update release
ordering in backend/src/releaseManager.ts lines 1257-1262 to compare ISO builtAt
values with direct chronological < or > comparisons and replace the commitSha
tie-breaker with a meaningful recency tie-break such as directory birth time. In
backend/test/releaseManager.test.ts lines 830-851, assign distinct builtAt
values to each managed release fixture so the retention assertion verifies
newest-first ordering; both sites require changes.

1257-1262: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Tie-break on equal builtAt is arbitrary.

builtAt is an ISO string compared with localeCompare, then ties fall back to descending commit SHA — a lexicographic SHA has no relation to recency, so two releases built in the same second can be ordered wrongly and the newer one pruned. Plain </> comparison on the ISO strings is also cheaper and locale-independent.

🤖 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/releaseManager.ts` around lines 1257 - 1262, Update the sorting
callback that creates newestFirst to compare ISO builtAt values with direct
lexicographic ordering rather than localeCompare, and replace the commitSha
tie-break with a recency-based field or ordering that reliably identifies which
equal-timestamp release is newer. Preserve newest-first ordering so pruning
retains the newer release.
🤖 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/releaseDeployment.ts`:
- Around line 411-418: Update the environment object in the release deployment
flow to explicitly set or remove MIRA_DASHBOARD_RELEASE_ROOT so the detached
build cannot inherit the service’s active-release value; ensure any default
release-root lookup resolves to the worktree being built, alongside the existing
MIRA_DASHBOARD_RELEASES_ROOT handling.

In `@backend/src/releaseManager.ts`:
- Around line 1228-1255: Update pruneDashboardReleases so an unverifiable
non-protected SHA-named release does not abort retention cleanup: catch
validation failures from loadManagedReleaseFromLayout, warn, and treat that
release as prunable or otherwise continue processing. Preserve error propagation
for protected releases, and ensure retired-entry cleanup still proceeds.

In `@backend/src/services/logRotation.ts`:
- Around line 2048-2059: Update elevatedLogRotationEnvironment and the elevated
log-rotation locking flow to preserve and use
MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE instead of falling back to the module’s
default lock path. Ensure elevated and non-elevated execution share the
configured lock file, and add coverage exercising both paths with distinct
configured lock files to verify no second default lock is created.

In `@backend/src/services/pullRequests.ts`:
- Line 1537: The readiness checks must use the configured effective Dashboard
port instead of hardcoded 3100. In backend/src/services/pullRequests.ts lines
1537-1537, update the readiness URL construction in the relevant cutover path to
use the validated service-port value; in docs/setup/production-deploy.md lines
182-188, define and use the same effective port in ready_for_commit. Ensure both
cutover paths consistently probe the configured port.

In `@docs/setup/production-deploy.md`:
- Around line 83-87: Update the “One-Time Managed Cutover” instructions to
require the managed cutover directly after merging the control checkout, without
deploying through or relying on the old in-place executor. Remove the
prerequisite that the old deployment must build or run this change, while
preserving the idle Jobs queue and known-good bootstrap release requirements.
- Around line 174-197: Update docs/setup/production-deploy.md lines 174-197
around ready_for_commit and "$BOOTSTRAP_SHA" so a failed bootstrap readiness
check enters the documented unit/state recovery flow and exits 1. Update lines
227-250 to explicitly invoke ready_for_commit for the candidate, and on failure
roll back, verify bootstrap readiness with ready_for_commit, then exit nonzero
before cleanup.

---

Nitpick comments:
In `@backend/src/releaseManager.ts`:
- Around line 1257-1262: Update release ordering in
backend/src/releaseManager.ts lines 1257-1262 to compare ISO builtAt values with
direct chronological < or > comparisons and replace the commitSha tie-breaker
with a meaningful recency tie-break such as directory birth time. In
backend/test/releaseManager.test.ts lines 830-851, assign distinct builtAt
values to each managed release fixture so the retention assertion verifies
newest-first ordering; both sites require changes.
- Around line 1257-1262: Update the sorting callback that creates newestFirst to
compare ISO builtAt values with direct lexicographic ordering rather than
localeCompare, and replace the commitSha tie-break with a recency-based field or
ordering that reliably identifies which equal-timestamp release is newer.
Preserve newest-first ordering so pruning retains the newer release.

In `@backend/src/services/logRotation.ts`:
- Around line 71-86: Extract the absolute, non-root path validation from
resolveLogRotationLockFile and resolveAbsoluteNonRootPath into one shared
helper, preserving trimming, null-byte rejection, absolute-path enforcement, and
non-root rejection. Update both callers to use the shared helper and reuse a
single resolved-path computation within it instead of repeatedly calling
path.resolve.

In `@backend/test/releaseDeployment.test.ts`:
- Around line 254-307: Make the concurrency barrier in the “accepts a
concurrently published copy of the same verified release” test bounded so
buildsReleased cannot wait indefinitely if either stageDashboardRelease call
exits early or fails. Race the deploy:prepare synchronization wait against a
short timeout, while preserving the existing two-build coordination and
shared-path assertions.

In `@backend/test/serviceBehavior.test.ts`:
- Around line 50-109: Extract createDeploymentReleaseFixture and the shared
release-artifact setup into a reusable helper under the test support area, then
update serviceBehavior.test.ts and releaseDeployment.test.ts to use it. Preserve
the existing directory tree, lockfiles, build-identity payloads, entrypoint
list, and writeReleaseManifest inputs so both tests continue validating the same
release contract from one implementation.

In `@systemd/mira-dashboard-worker.service`:
- Around line 9-18: Verify WorkingDirectory and all five Environment values in
systemd/mira-dashboard-worker.service lines 9-18 against
managedDashboardUnitContract(), then add a unit test parsing that file and
passing its properties to
assertManagedDashboardUnitProperties("mira-dashboard-worker.service", …). Apply
the same verification and equivalent assertion for
systemd/mira-dashboard.service lines 9-18 using "mira-dashboard.service",
ensuring both shipped unit files are covered by CI.
🪄 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: 6359a8d8-68b5-4ca6-a853-9aa2b0bb2a12

📥 Commits

Reviewing files that changed from the base of the PR and between 4aca68e and b81e27c.

📒 Files selected for processing (28)
  • backend/src/releaseDeployment.ts
  • backend/src/releaseLifecycle.ts
  • backend/src/releaseManager.ts
  • backend/src/releaseManifest.ts
  • backend/src/requestPolicy.ts
  • backend/src/routes.ts
  • backend/src/services/logRotation.ts
  • backend/src/services/pullRequests.ts
  • backend/test/bunNativeServerBehavior.test.ts
  • backend/test/healthReadiness.test.ts
  • backend/test/httpApiBehavior.test.ts
  • backend/test/releaseDeployment.test.ts
  • backend/test/releaseManager.test.ts
  • backend/test/releaseManifest.test.ts
  • backend/test/serviceBehavior.test.ts
  • backend/test/testDatabaseGuard.test.ts
  • docs/api/overview.md
  • docs/architecture/database.md
  • docs/architecture/gateway-and-chat.md
  • docs/index.md
  • docs/operations/runbooks.md
  • docs/operations/scheduler-cache-backups.md
  • docs/security/auth-and-trust-boundaries.md
  • docs/setup/new-vps.md
  • docs/setup/production-deploy.md
  • docs/setup/secrets-and-env.md
  • systemd/mira-dashboard-worker.service
  • systemd/mira-dashboard.service
💤 Files with no reviewable changes (6)
  • docs/api/overview.md
  • backend/src/routes.ts
  • backend/test/httpApiBehavior.test.ts
  • backend/src/requestPolicy.ts
  • backend/test/bunNativeServerBehavior.test.ts
  • backend/test/releaseManifest.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: frontend-checks
  • GitHub Check: backend-checks
  • GitHub Check: Analyze JavaScript and TypeScript
🧰 Additional context used
🪛 ast-grep (0.44.1)
backend/test/releaseManager.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

backend/src/releaseManager.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

backend/src/releaseDeployment.ts

[warning] 96-96: Do not use variable for regular expressions
Context: new RegExp(String.raw(?:^|[\s"])${escaped}(?=$|[\s"]), "u")
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)


[warning] 103-103: Do not use variable for regular expressions
Context: new RegExp(String.raw(?:^|[\s";])${escaped}(?=$|[\s";]), "u")
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

🔇 Additional comments (30)
backend/src/services/pullRequests.ts (1)

12-23: LGTM!

Also applies to: 1464-1485, 1584-1634, 1636-1664

docs/setup/new-vps.md (1)

46-122: LGTM!

Also applies to: 261-261

docs/setup/production-deploy.md (1)

3-81: LGTM!

Also applies to: 129-172, 252-386

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

147-156: LGTM!

docs/architecture/database.md (1)

11-19: LGTM!

Also applies to: 74-107, 154-156, 170-174, 200-204

docs/architecture/gateway-and-chat.md (1)

620-621: LGTM!

docs/index.md (1)

51-55: LGTM!

docs/operations/runbooks.md (1)

63-67: LGTM!

Also applies to: 76-77, 87-87, 112-114, 160-167, 191-208, 278-282

docs/operations/scheduler-cache-backups.md (1)

235-250: LGTM!

Also applies to: 260-260

docs/security/auth-and-trust-boundaries.md (1)

113-114: LGTM!

docs/setup/secrets-and-env.md (1)

26-63: LGTM!

backend/src/releaseDeployment.ts (8)

23-107: LGTM!


109-156: LGTM!


158-214: LGTM!


216-304: LGTM!


306-370: LGTM!


541-551: LGTM!


532-535: 🗄️ Data Integrity & Integration

No change needed for retainCount validation.

prunePublishedDashboardReleases delegates to pruneDashboardReleases, which rejects non-safe integers and counts outside 2..20, so invalid CLI values like non-numeric, negative, fractional, zero, or empty input fail before prune runs.

			> Likely an incorrect or invalid review comment.

445-465: 🩺 Stability & Availability

No change needed. NODE_ENV=production does not make bun install omit devDependencies; bun install --production or --omit=dev is required for production-only installs.

backend/src/releaseManifest.ts (4)

29-39: LGTM!

Also applies to: 63-71


510-558: LGTM!


574-574: LGTM!

Also applies to: 610-612, 629-629


763-765: LGTM!

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

22-22: LGTM!

Also applies to: 46-46

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

1-213: LGTM!

Also applies to: 309-535

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

9-9: LGTM!

Also applies to: 21-27, 1879-1915, 1926-1939, 1957-1996, 2057-2104

backend/src/releaseManager.ts (2)

32-33: LGTM!

Also applies to: 58-62, 407-416, 1211-1227, 1263-1317


645-663: 🩺 Stability & Availability

No change needed. schema.migrations is non-optional in DashboardReleaseManifest, generated by parseSchema, and included by createReleaseManifest, so this access path does not rely on an absent field.

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

7-7: LGTM!

Also applies to: 74-81

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

33-33: LGTM!

Also applies to: 52-52, 387-397, 862-873

Comment thread backend/src/releaseDeployment.ts Outdated
Comment thread backend/src/releaseManager.ts
Comment thread backend/src/services/logRotation.ts Outdated
Comment thread backend/src/services/pullRequests.ts Outdated
Comment thread docs/setup/production-deploy.md Outdated
Comment thread docs/setup/production-deploy.md Outdated
@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: bdebc02232

ℹ️ 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 docs/operations/runbooks.md Outdated
Comment thread backend/src/routes.ts
Comment thread docs/setup/production-deploy.md 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: 2bb231386e

ℹ️ 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/services/pullRequests.ts Outdated
Comment thread backend/src/services/pullRequests.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.

🧹 Nitpick comments (1)
backend/src/services/logRotation.ts (1)

72-78: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider deduplicating the two preserved-env allowlists.

ELEVATED_LOG_ROTATION_PRESERVED_ENVIRONMENT (sudo --preserve-env) and the allowed array in elevatedLogRotationEnvironment() (env forwarded to the spawned bun process) share most entries (LANG, NODE_ENV, TZ, MIRA_DASHBOARD_DB_PATH, MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE), differing only by PATH/HOME. Keeping them as separate literals risks drift if a future variable needs to be added to only one list.

♻️ Suggested consolidation
-const ELEVATED_LOG_ROTATION_PRESERVED_ENVIRONMENT = [
-    "LANG",
-    "NODE_ENV",
-    "TZ",
-    "MIRA_DASHBOARD_DB_PATH",
-    "MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE",
-] as const;
+const ELEVATED_LOG_ROTATION_FORWARDED_VARIABLES = [
+    "LANG",
+    "NODE_ENV",
+    "TZ",
+    "MIRA_DASHBOARD_DB_PATH",
+    "MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE",
+] as const;
+const ELEVATED_LOG_ROTATION_PRESERVED_ENVIRONMENT = ELEVATED_LOG_ROTATION_FORWARDED_VARIABLES;
 function elevatedLogRotationEnvironment(): NodeJS.ProcessEnv {
-    const allowed = [
-        "PATH",
-        "HOME",
-        "LANG",
-        "NODE_ENV",
-        "TZ",
-        "MIRA_DASHBOARD_DB_PATH",
-        "MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE",
-    ];
+    const allowed = ["PATH", "HOME", ...ELEVATED_LOG_ROTATION_FORWARDED_VARIABLES];

Also applies to: 2053-2062

🤖 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/logRotation.ts` around lines 72 - 78, Deduplicate the
shared environment names used by ELEVATED_LOG_ROTATION_PRESERVED_ENVIRONMENT and
the allowed list in elevatedLogRotationEnvironment(). Define the common entries
once and derive or reuse them in both flows, while retaining PATH and HOME only
where required by the spawned bun process.
🤖 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.

Nitpick comments:
In `@backend/src/services/logRotation.ts`:
- Around line 72-78: Deduplicate the shared environment names used by
ELEVATED_LOG_ROTATION_PRESERVED_ENVIRONMENT and the allowed list in
elevatedLogRotationEnvironment(). Define the common entries once and derive or
reuse them in both flows, while retaining PATH and HOME only where required by
the spawned bun process.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6c806bbf-8110-4f85-9ff1-9e73ef759c94

📥 Commits

Reviewing files that changed from the base of the PR and between b81e27c and 2bb2313.

📒 Files selected for processing (18)
  • backend/package.json
  • backend/src/lib/safePath.ts
  • backend/src/lib/values.ts
  • backend/src/releaseDeployment.ts
  • backend/src/releaseManager.ts
  • backend/src/server.ts
  • backend/src/services/logRotation.ts
  • backend/src/services/pullRequests.ts
  • backend/test/bunNativeServerBehavior.test.ts
  • backend/test/releaseDeployment.test.ts
  • backend/test/releaseManager.test.ts
  • backend/test/serviceBehavior.test.ts
  • backend/test/support/releaseFixture.ts
  • backend/test/utilityBehavior.test.ts
  • docs/operations/runbooks.md
  • docs/setup/production-deploy.md
  • systemd/mira-dashboard-worker.service
  • systemd/mira-dashboard.service
🚧 Files skipped from review as they are similar to previous changes (6)
  • systemd/mira-dashboard.service
  • systemd/mira-dashboard-worker.service
  • backend/src/releaseDeployment.ts
  • backend/src/services/pullRequests.ts
  • docs/operations/runbooks.md
  • docs/setup/production-deploy.md
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: frontend-checks
  • GitHub Check: backend-checks
🧰 Additional context used
🪛 ast-grep (0.44.1)
backend/src/services/logRotation.ts

[error] 2064-2068: Recursive/iterative merge copies attacker-controllable keys from a source object into a target via a computed property assignment without rejecting dangerous keys, allowing prototype pollution. Skip or block "proto", "constructor", and "prototype" keys (e.g. if (key === "__proto__" || key === "constructor" || key === "prototype") continue;), use a null-prototype object (Object.create(null)), or use a safe merge utility instead.
Context: for (const key of allowed) {
if (process.env[key] !== undefined) {
environment[key] = process.env[key];
}
}
Note: [CWE-1321] Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution').

(prototype-pollution-recursive-merge-typescript)

backend/src/releaseManager.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

backend/test/releaseManager.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🔇 Additional comments (18)
backend/src/releaseManager.ts (3)

1202-1340: 🩺 Stability & Availability

Retention pruning: past critical retention-abort bug is now resolved.

The previously-flagged issue (an unverifiable non-protected release directory aborting prune 3 entirely) is fixed here: loadManagedReleaseFromLayout failures for non-protected commits are now caught, recorded in warnings, and treated as prunable-skip candidates, while protected (current/previous) commit failures still re-throw. Sort/tie-break, TOCTOU re-verification before rename, post-rename inode identity check, and retired-directory cleanup all look correct.


16-16: LGTM!

Also applies to: 27-34, 59-64, 322-352, 354-361, 394-396


636-654: 🗄️ Data Integrity & Integration

schema.migrations is already required.

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

831-905: 🩺 Stability & Availability

Good coverage confirming the retention-abort fix.

This test directly exercises the previously-reported scenario (unverifiable release directory + interrupted retirement leftovers) and asserts pruning still proceeds, preserves current/previous, and surfaces a warning instead of throwing. Matches the fixed behavior in releaseManager.ts.


114-180: LGTM!


388-399: LGTM!

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

1-548: LGTM!


30-43: 🎯 Functional Correctness

No change needed.

The shipped units use unquoted Environment=KEY=VALUE lines, so managedUnitProperties does not introduce quoted tokens for this test path.

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

1-70: LGTM on the rest of the fixture — comprehensive artifact set (manifest, lockfiles, entrypoints, non-artifact noise file) matches the immutable-release publish contract described in the stack context.


42-50: 🗄️ Data Integrity & Integration

No change needed.

backend/src/releaseManifest.ts still validates component build-identity.json as formatVersion: 1, so the fixture matches the enforced build-identity schema.

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

338-341: LGTM! Matches the updated staticResponse 404 behavior for the retired /health route.

Also applies to: 520-520

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

9-9: LGTM! Deployment/log-rotation test updates are internally consistent with releaseManager.ts and logRotation.ts contracts (managed layout, env-preserving sudo/doppler invocations, detached-cutover ordering assertions).

Also applies to: 21-27, 1819-2032, 5008-5103

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

22-22: LGTM! Assertions match resolveDashboardPort/resolveAbsoluteNonRootPath implementations exactly, including boundary cases.

Also applies to: 32-32, 410-413, 451-456

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

7-7: 🩺 Stability & Availability

Prior critical lock-file mismatch is fixed.

The elevated sudo path now preserves and forwards MIRA_DASHBOARD_LOG_ROTATION_LOCK_FILE consistently (--preserve-env allowlist + elevatedLogRotationEnvironment()), and resolveLogRotationLockFile() reads the same env var for both elevated and non-elevated runs. This resolves the previously flagged dual-lock-file race.

Also applies to: 72-85, 1488-1503, 1526-1527, 1628-1637, 2042-2042, 2053-2071

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

41-53: LGTM!

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

13-22: LGTM!

backend/src/server.ts (1)

18-18: LGTM!

Also applies to: 80-80, 103-103, 234-236

backend/package.json (1)

12-12: LGTM!

@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: 337d3568ca

ℹ️ 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/services/scheduledJobs.ts
Comment thread backend/src/releaseManager.ts Outdated
Comment thread backend/src/releaseDeployment.ts Outdated
Comment thread backend/src/services/pullRequests.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: 2

Caution

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

⚠️ Outside diff range comments (1)
backend/src/releaseManager.ts (1)

1206-1207: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Require at least three retained releases.

The release contract requires retaining current, previous, and one additional verified release, but this validation accepts retainCount = 2. Since the retention set already starts with the two protected commits, that value can remove the additional rollback fallback.

Proposed fix
-    if (!Number.isSafeInteger(retainCount) || retainCount < 2 || retainCount > 20) {
+    if (!Number.isSafeInteger(retainCount) || retainCount < 3 || retainCount > 20) {
🤖 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/releaseManager.ts` around lines 1206 - 1207, Update the
retainCount validation in the release manager to reject values below 3 while
preserving the safe-integer check and maximum of 20. Ensure the resulting error
message states the managed release retention range as 3 to 20.
🧹 Nitpick comments (1)
backend/src/services/scheduledJobs.ts (1)

1285-1331: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Prepared statements rebuilt on every reconcile pass.

database.prepare(...) inside the transaction closure runs per call (every 5s). Hoisting the two statements to module scope (or relying on cached query()) trims avoidable parse work. Optional.

🤖 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/scheduledJobs.ts` around lines 1285 - 1331, Hoist or
cache the UPDATE and DELETE prepared statements used by failOrphanedCutover in
reconcileOrphanedDeploymentCutovers so they are not rebuilt for each
reconciliation pass or job. Preserve the transaction, status guard, timestamp
updates, and lock cleanup behavior.
🤖 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/services/scheduledJobs.ts`:
- Around line 1333-1354: Update hasPendingDeploymentCutover and its
reconciliation flow to provide an escape hatch for restart-scheduled rows that
remain stale when guardian checks cannot complete, such as systemctl failures.
Before returning the pending-row gate, clear or otherwise resolve rows exceeding
a bounded age or reconcile-attempt window, while preserving normal
reconciliation for active cutovers and avoiding indefinite worker claim pauses.
- Around line 1262-1283: Update readDeploymentGuardianState to distinguish a
genuine inactive systemd unit from a missing unit or command failure: inspect
result.exitCode and decoded stderr before mapping the "unknown" stdout state to
"inactive". Only return "inactive" for a confirmed non-error inactive/failed
condition; otherwise return "unknown" so reconcileOrphanedDeploymentCutovers()
defers the cutover.

---

Outside diff comments:
In `@backend/src/releaseManager.ts`:
- Around line 1206-1207: Update the retainCount validation in the release
manager to reject values below 3 while preserving the safe-integer check and
maximum of 20. Ensure the resulting error message states the managed release
retention range as 3 to 20.

---

Nitpick comments:
In `@backend/src/services/scheduledJobs.ts`:
- Around line 1285-1331: Hoist or cache the UPDATE and DELETE prepared
statements used by failOrphanedCutover in reconcileOrphanedDeploymentCutovers so
they are not rebuilt for each reconciliation pass or job. Preserve the
transaction, status guard, timestamp updates, and lock cleanup 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: 290a1ec9-4043-42bd-aef3-3d5c53c4ce3f

📥 Commits

Reviewing files that changed from the base of the PR and between 2bb2313 and ef93157.

📒 Files selected for processing (8)
  • backend/src/releaseDeployment.ts
  • backend/src/releaseManager.ts
  • backend/src/services/logRotation.ts
  • backend/src/services/pullRequests.ts
  • backend/src/services/scheduledJobs.ts
  • backend/test/jobExecutionQueue.test.ts
  • backend/test/releaseDeployment.test.ts
  • backend/test/serviceBehavior.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • backend/test/releaseDeployment.test.ts
  • backend/src/services/logRotation.ts
  • backend/src/releaseDeployment.ts
  • backend/test/serviceBehavior.test.ts
  • backend/src/services/pullRequests.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: frontend-checks
  • GitHub Check: backend-checks
🧰 Additional context used
🪛 ast-grep (0.44.1)
backend/src/releaseManager.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🔇 Additional comments (3)
backend/src/services/scheduledJobs.ts (1)

36-39: LGTM!

Also applies to: 56-56, 66-72, 1259-1260

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

1-1: LGTM!

Also applies to: 27-27, 40-40, 51-59, 81-130


131-135: 🎯 Functional Correctness

No change needed. The project runs tests with bun test and database.ts imports bun:sqlite, so Statement.get() returning null for no rows is the active driver behavior.

			> Likely an incorrect or invalid review comment.

Comment thread backend/src/services/scheduledJobs.ts Outdated
Comment thread backend/src/services/scheduledJobs.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: ef9315758c

ℹ️ 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/services/scheduledJobs.ts
Comment thread docs/setup/production-deploy.md Outdated
@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: efb03a3c6a

ℹ️ 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/services/pullRequests.ts Outdated
Comment thread backend/src/services/pullRequests.ts Outdated
Comment thread backend/src/services/pullRequests.ts Outdated
Comment thread systemd/mira-dashboard.service Outdated
Comment thread backend/src/releaseManager.ts

@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

🧹 Nitpick comments (3)
backend/src/services/scheduledJobs.ts (2)

1418-1429: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Pending gate never clears when no recovery handler is registered.

reconcileOrphanedDeploymentCutovers() falls back to scheduledJobRuntimeState.deploymentCutoverRecoveryHandler; if it is undefined (registration skipped, e.g. a worker-only process that never calls registerPullRequestExecutionActions), every restart-scheduled row is skipped and executorTick() pauses claims forever with no diagnostic. A one-time warning when a recoverable cutover is found without a handler would make that state observable.

🤖 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/scheduledJobs.ts` around lines 1418 - 1429, The
hasPendingDeploymentCutover flow should detect when recoverable
restart-scheduled cutovers exist but
scheduledJobRuntimeState.deploymentCutoverRecoveryHandler is undefined. Emit a
one-time warning identifying the missing recovery handler and affected cutovers,
while preserving normal reconciliation and avoiding repeated warnings on every
executorTick.

1276-1322: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Non-empty stderr on a successful systemctl show degrades to unknown.

systemctl show can print benign diagnostics to stderr while exiting 0. Gating on stderr || therefore biases toward unknown, which defers reconciliation until the 10-minute bound expires and then triggers rollback recovery for a possibly-healthy cutover. Consider keying only on exitCode !== 0 plus unparseable output, and logging stderr instead.

♻️ Suggested change
-    const stderr = new TextDecoder().decode(result.stderr).trim();
-    if (stderr || result.exitCode !== 0) {
+    if (result.exitCode !== 0) {
+        console.warn(
+            "[ScheduledJobs] systemctl show failed:",
+            new TextDecoder().decode(result.stderr).trim()
+        );
         return "unknown";
     }
🤖 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/scheduledJobs.ts` around lines 1276 - 1322, Update
readSystemdUnitState to stop treating non-empty stderr as failure when systemctl
exits successfully; gate the unknown result on result.exitCode !== 0 and
unparseable or missing required output instead. Preserve stderr for diagnostic
logging rather than using it to override a successful state determination.
backend/test/jobExecutionQueue.test.ts (1)

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

Expired-unknown path is only covered via the throwing reader.

The post-bound assertion uses a reader that throws, which reaches the same branch only because state defaults to "unknown". Add a case with () => "unknown" at 03:11 so the intended bounded-unknown expiry is asserted directly and stays covered if the catch-block default ever changes.

🤖 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/jobExecutionQueue.test.ts` around lines 136 - 166, Extend the
test around reconcileOrphanedDeploymentCutovers with a separate post-bound
invocation at 03:11 using a reader that returns "unknown" without throwing, and
assert it schedules one recovery. Keep the existing throwing-reader case and
warning assertions unchanged so the bounded-unknown expiry path is covered
independently of catch-block defaults.
🤖 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 1244-1288: Protect the entire staging write, verification, and
activation sequence in the release creation flow with
withReleaseTransitionLock(layout, "exclusive", ...), starting before stagingPath
is created and ending after it is deleted or renamed to finalPath. Ensure
copyVerifiedRelease and all related staging operations execute under this lock
so pruneDashboardReleases cannot remove an in-progress .staging-* directory;
leave the existing cleanup validation around the pruner unchanged.

---

Nitpick comments:
In `@backend/src/services/scheduledJobs.ts`:
- Around line 1418-1429: The hasPendingDeploymentCutover flow should detect when
recoverable restart-scheduled cutovers exist but
scheduledJobRuntimeState.deploymentCutoverRecoveryHandler is undefined. Emit a
one-time warning identifying the missing recovery handler and affected cutovers,
while preserving normal reconciliation and avoiding repeated warnings on every
executorTick.
- Around line 1276-1322: Update readSystemdUnitState to stop treating non-empty
stderr as failure when systemctl exits successfully; gate the unknown result on
result.exitCode !== 0 and unparseable or missing required output instead.
Preserve stderr for diagnostic logging rather than using it to override a
successful state determination.

In `@backend/test/jobExecutionQueue.test.ts`:
- Around line 136-166: Extend the test around
reconcileOrphanedDeploymentCutovers with a separate post-bound invocation at
03:11 using a reader that returns "unknown" without throwing, and assert it
schedules one recovery. Keep the existing throwing-reader case and warning
assertions unchanged so the bounded-unknown expiry path is covered independently
of catch-block defaults.
🪄 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: bd47f614-ad08-42cf-8563-ec91c7b5267e

📥 Commits

Reviewing files that changed from the base of the PR and between ef93157 and 862b474.

📒 Files selected for processing (14)
  • backend/src/releaseDeployment.ts
  • backend/src/releaseManager.ts
  • backend/src/services/jobExecutionQueue.ts
  • backend/src/services/pullRequests.ts
  • backend/src/services/scheduledJobs.ts
  • backend/test/jobExecutionQueue.test.ts
  • backend/test/releaseDeployment.test.ts
  • backend/test/releaseManager.test.ts
  • backend/test/serviceBehavior.test.ts
  • docs/setup/production-deploy.md
  • docs/setup/secrets-and-env.md
  • src/pages/PullRequests.tsx
  • systemd/mira-dashboard-worker.service
  • systemd/mira-dashboard.service
🚧 Files skipped from review as they are similar to previous changes (8)
  • systemd/mira-dashboard.service
  • systemd/mira-dashboard-worker.service
  • docs/setup/secrets-and-env.md
  • backend/test/releaseDeployment.test.ts
  • backend/src/releaseDeployment.ts
  • backend/test/serviceBehavior.test.ts
  • docs/setup/production-deploy.md
  • backend/src/services/pullRequests.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: backend-checks
  • GitHub Check: frontend-checks
🧰 Additional context used
🪛 ast-grep (0.44.1)
backend/test/releaseManager.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

backend/src/releaseManager.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🪛 OpenGrep (1.25.0)
backend/src/releaseManager.ts

[ERROR] 1244-1244: 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 (10)
src/pages/PullRequests.tsx (1)

302-302: LGTM!

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

37-41: LGTM!

Also applies to: 50-77


1343-1409: LGTM!


1324-1341: 🩺 Stability & Availability

No change needed. The cutover status is written before the systemd-run guardian is scheduled, so neither side creates an earlier restart-scheduled/missing window to reconcile.

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

80-134: LGTM!


167-189: LGTM!

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

17-17: LGTM!

Also applies to: 435-435, 474-476

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

13-13: LGTM!

Also applies to: 395-396, 872-887, 906-922

backend/src/releaseManager.ts (2)

35-37: LGTM!


1209-1211: LGTM!

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: 862b474de7

ℹ️ 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 docs/setup/production-deploy.md Outdated
Comment thread docs/setup/production-deploy.md Outdated
Comment thread backend/src/services/pullRequests.ts Outdated
@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 21f7242f46

ℹ️ 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".

@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@mira-2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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

🧹 Nitpick comments (2)
backend/test/jobExecutionQueue.test.ts (2)

252-293: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Setup steps run outside the try/finally, risking a leaked temp dir on failure.

mkdtempSync, writeFileSync, chmodSync, and the process.env.PATH mutation all happen before the try block. If any of them throws, rmSync(fakeBin, ...) in finally never runs and the temp directory leaks. Low likelihood, but easy to close by moving these into the guarded region.

🧹 Proposed fix to guard setup as well
-        const startedAt = "2026-07-26T03:00:00.000Z";
-        createRestartScheduledDeployment(startedAt);
-        const fakeBin = mkdtempSync(path.join(tmpdir(), "mira-systemctl-test-"));
-        const systemctl = path.join(fakeBin, "systemctl");
-        const originalPath = process.env.PATH;
-        writeFileSync(
-            systemctl,
-            String.raw`#!/usr/bin/env bash
-printf 'benign diagnostic\n' >&2
-printf 'LoadState=loaded\nActiveState=active\n'
-`
-        );
-        chmodSync(systemctl, 0o755);
-        process.env.PATH = `${fakeBin}${path.delimiter}${originalPath ?? ""}`;
-        const warning = jest.spyOn(console, "warn").mockImplementation(() => {});
-        const recovery = jest.fn(() => true);
-        try {
+        const startedAt = "2026-07-26T03:00:00.000Z";
+        createRestartScheduledDeployment(startedAt);
+        const fakeBin = mkdtempSync(path.join(tmpdir(), "mira-systemctl-test-"));
+        const originalPath = process.env.PATH;
+        try {
+            const systemctl = path.join(fakeBin, "systemctl");
+            writeFileSync(
+                systemctl,
+                String.raw`#!/usr/bin/env bash
+printf 'benign diagnostic\n' >&2
+printf 'LoadState=loaded\nActiveState=active\n'
+`
+            );
+            chmodSync(systemctl, 0o755);
+            process.env.PATH = `${fakeBin}${path.delimiter}${originalPath ?? ""}`;
+            const warning = jest.spyOn(console, "warn").mockImplementation(() => {});
+            const recovery = jest.fn(() => true);
🤖 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/jobExecutionQueue.test.ts` around lines 252 - 293, Move the
temporary-directory setup, fake systemctl creation, permissions update, and PATH
mutation into the try/finally guarded by the existing cleanup in the test around
reconcileOrphanedDeploymentCutovers. Ensure cleanup safely handles setup
failures, including when fakeBin was not created, while preserving the current
assertions and environment restoration.

169-194: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an exact 10-minute boundary probe for unknown guardian state.

isDeploymentCutoverReconciliationExpired expires when the delta reaches >= 10 * 60 * 1000, but this test only shows no recovery at 1 minute and recovery at 11 minutes. A probe at 03:10:00.000Z would catch an off-by-one such as > vs >= in this reliability-critical reconciliation path.

🤖 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/jobExecutionQueue.test.ts` around lines 169 - 194, Add an
assertion in the test covering reconcileOrphanedDeploymentCutovers for unknown
guardian state at exactly 03:10:00.000Z, verifying recovery is scheduled and
called with the expected deployment details. Keep the existing 1-minute and
11-minute checks intact.
🤖 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/test/releaseManager.test.ts`:
- Around line 295-301: Replace the fixed Bun.sleep delay in the
publishVerifiedDashboardRelease test with a deterministic barrier or test hook
that confirms execution has reached lock acquisition and is waiting for the
transition lock before checking the releases directory. Keep the assertion that
no .staging- directory exists, but ensure it runs only after that
synchronization point.

---

Nitpick comments:
In `@backend/test/jobExecutionQueue.test.ts`:
- Around line 252-293: Move the temporary-directory setup, fake systemctl
creation, permissions update, and PATH mutation into the try/finally guarded by
the existing cleanup in the test around reconcileOrphanedDeploymentCutovers.
Ensure cleanup safely handles setup failures, including when fakeBin was not
created, while preserving the current assertions and environment restoration.
- Around line 169-194: Add an assertion in the test covering
reconcileOrphanedDeploymentCutovers for unknown guardian state at exactly
03:10:00.000Z, verifying recovery is scheduled and called with the expected
deployment details. Keep the existing 1-minute and 11-minute checks intact.
🪄 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: 9fde9069-d486-4798-8043-55e7d93a4b78

📥 Commits

Reviewing files that changed from the base of the PR and between 862b474 and 178686d.

📒 Files selected for processing (8)
  • backend/src/releaseDeployment.ts
  • backend/src/releaseManager.ts
  • backend/src/services/pullRequests.ts
  • backend/src/services/scheduledJobs.ts
  • backend/test/jobExecutionQueue.test.ts
  • backend/test/releaseManager.test.ts
  • backend/test/serviceBehavior.test.ts
  • docs/setup/production-deploy.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • backend/src/services/scheduledJobs.ts
  • docs/setup/production-deploy.md
  • backend/test/serviceBehavior.test.ts
  • backend/src/services/pullRequests.ts
📜 Review details
🧰 Additional context used
🪛 ast-grep (0.44.1)
backend/src/releaseManager.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

backend/test/releaseManager.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🔇 Additional comments (12)
backend/test/releaseManager.test.ts (1)

13-13: LGTM!

Also applies to: 34-35, 49-55, 121-122, 176-176, 417-428, 860-939, 941-952

backend/src/releaseDeployment.ts (3)

12-12: LGTM!


291-427: LGTM!


436-462: LGTM!

backend/src/releaseManager.ts (5)

39-40: LGTM!

Also applies to: 68-68


138-146: LGTM!


970-1039: LGTM!


1041-1148: LGTM!


1335-1523: LGTM!

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

1-4: LGTM!

Also applies to: 31-31


140-167: LGTM!


44-99: LGTM!

Comment thread backend/test/releaseManager.test.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: 178686dba2

ℹ️ 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/services/scheduledJobs.ts
Comment thread backend/src/services/pullRequests.ts
Comment thread backend/src/services/pullRequests.ts Outdated
Comment thread backend/src/services/pullRequests.ts
@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: c105e62513

ℹ️ 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 systemd/mira-dashboard.service
Comment thread docs/setup/production-deploy.md
@mira-2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 23237366ba

ℹ️ 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".

@mira-2026 mira-2026 removed status: needs-review Ready for human or agent review status: do-not-merge Must not be merged until explicitly cleared labels Jul 26, 2026
@mira-2026
mira-2026 merged commit 03677b4 into main Jul 26, 2026
7 checks passed
@mira-2026
mira-2026 deleted the atomic-release-cutover branch July 26, 2026 10:29
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: ops Operational actions, deploys, services, backups, and health priority: high High-priority work for the next active cycle type: feature Adds user-visible functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants