Skip to content

feat(greenfield): replace generic exec with service actions - #422

Open
mira-2026 wants to merge 13 commits into
mira/greenfield-rewrite-openclaw-operations-media-parityfrom
mira/greenfield-rewrite-ops-actions-parity
Open

feat(greenfield): replace generic exec with service actions#422
mira-2026 wants to merge 13 commits into
mira/greenfield-rewrite-openclaw-operations-media-parityfrom
mira/greenfield-rewrite-ops-actions-parity

Conversation

@mira-2026

@mira-2026 mira-2026 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Stack

Summary

  • replace consumed generic-exec behavior with purpose-built durable Service Actions while retaining the worker-owned PTY for terminal, cd, completion, and bounded termination
  • expose exactly six fixed actions: OpenClaw cleanup, restart, and update plus system cleanup, restart, and update
  • reuse the existing openclaw.gateway.restart definition, executor, and provider already used by Settings
  • render the complete Service Actions inventory directly on /jobs, including actions with no previous run, and open observed run IDs as exact Jobs details
  • keep the legacy /api/exec/start parity row planned until fixed host authority is executable through the approved production worker/root boundary

Security and durability

  • session-only read/write capabilities; mutations require recent MFA and forbid batching
  • audit attempt commits before enqueue, then session, MFA, and fresh worker availability are revalidated at the durable handoff
  • new Service Action runs persist the verified release ID; candidate selection and the atomic claim CAS both require that exact worker release, while ordinary jobs remain nullable and unfenced
  • all six actions use fixed code-owned definitions, attempt limit one, no cancellation, no retry after uncertain dispatch, and exact resource locks
  • no generic shell, caller command, cwd, path, environment, secret, raw process output, or provider error crosses the contract
  • OpenClaw cleanup/update use reviewed worker-owned Gateway operations; OpenClaw restart reuses the existing fixed lifecycle action

Fixed host-operation foundation

  • add one fixed /usr/bin/systemctl broker for exactly system-cleanup, system-restart, and system-update
  • system cleanup runs fixed package autoremove/cache cleanup, journald rotation with 14-day and 1 GiB bounds, and Docker pruning of unused content older than seven days; it attempts every phase and never deletes volumes
  • system restart returns accepted-only semantics and schedules the reviewed deferred reboot timer
  • before restart dispatch, the worker atomically requires the restart claim to be the only globally running job and arms a singleton fence bound to the exact run, worker, lease, Linux boot identity, and bounded expiry
  • while that same-boot fence is valid, all workers reject new claims; every ambiguous dispatch outcome retains the fence, and only a new boot or bounded same-boot expiry reconciles stale state

Production availability boundary

  • the release ships exact root-owned units, policy, broker, installer, and rollback artifacts, but production does not install or compose that authority in this PR
  • web and worker currently share one Unix identity, so authorizing that identity would also authorize the internet-facing web process
  • all three system actions therefore remain fail-closed unavailable until a separately reviewed topology gives the worker its own OS principal and separately approved root provisioning is activated
  • provisioning requires immutable root-owned staging, an exact root-owned Bun runtime and staged entrypoint, no-follow ownership/mode/content verification, and an out-of-band approved release-manifest.json SHA-256 trust anchor

Development reliability

  • add a development-only Bun plugin that defers TanStack Router's cyclic replaceRouteChunk access and full-reloads only lazy-route HMR; ordinary React/CSS Fast Refresh remains enabled and production builds are unaffected
  • make the outer development coordinator monitor the semantic migration graph independently of Bun's watched children
  • on a reviewed migration change, stop frontend/web/worker together, reset only development SQLite and its sidecars, wait for a valid graph, then restart the complete stack
  • automatically recover when a watched child sees a partially written migration graph instead of leaving the frontend serving a persistent session-check failure

Parity

  • legacy endpoints: 112 implemented / 42 planned / 3 reviewed removals = 157
  • frontend routes: 12 implemented / 4 planned = 16
  • /api/exec/start remains planned until system-cleanup is executable through the approved production worker/root boundary

Verification

  • Bun suite: 2,764 passed
  • browser suite: 815 passed
  • browser, process, and Storybook production builds
  • shell, polkit, and systemd syntax verification for fixed host-operation artifacts
  • migration and snapshot SHA-256 verification against the reviewed manifest
  • independent full-diff review with no remaining P1/P2 findings
  • CI is the final post-push gate

@mira-2026
mira-2026 requested a review from rajohan as a code owner August 12, 2026 11:45
@mira-2026 mira-2026 added status: needs-review Ready for human or agent review type: feature Adds user-visible functionality type: tests Adds or updates automated tests/coverage type: security Security, auth, secrets, or trust-boundary work area: openclaw OpenClaw gateway/API integration and runtime behavior 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 type: documentation Documentation, README, comments, and operational notes labels Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 102 files, which is 2 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f0fbad0-be14-4000-8e48-b960ed457bbd

📥 Commits

Reviewing files that changed from the base of the PR and between eb71e93 and 67fe27c.

⛔ Files ignored due to path filters (3)
  • greenfield/docs/generated/schemas/serviceActions.getStatus.output.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/serviceActions.request.input.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/serviceActions.request.output.schema.json is excluded by !**/generated/** and included by **/*
📒 Files selected for processing (102)
  • greenfield/bunfig.toml
  • greenfield/docs/architecture/greenfield-rewrite/application-architecture.md
  • greenfield/docs/architecture/greenfield-rewrite/data-and-security.md
  • greenfield/docs/architecture/greenfield-rewrite/implementation-plan.md
  • greenfield/docs/architecture/greenfield-rewrite/progress.md
  • greenfield/docs/architecture/greenfield-rewrite/runtime-and-delivery.md
  • greenfield/docs/development/local-development.md
  • greenfield/migrations/20260804022252_dashboard-foundation/migration.sql
  • greenfield/migrations/20260804022252_dashboard-foundation/snapshot.json
  • greenfield/scripts/audits/openclaw/fixtures/2026.7.2-beta.7/manifest.json
  • greenfield/scripts/audits/openclaw/fixtures/2026.7.2-beta.7/operations.json
  • greenfield/scripts/audits/openclaw/sourceAudit.ts
  • greenfield/scripts/audits/openclaw/sourceAuditSchemas.ts
  • greenfield/scripts/delivery/buildRelease.test.ts
  • greenfield/scripts/delivery/hostOperationsProvisioningPolicy.test.ts
  • greenfield/scripts/delivery/hostOperationsProvisioningPolicy.ts
  • greenfield/scripts/delivery/installHostOperationsProvisioning.test.ts
  • greenfield/scripts/delivery/productionReleasePublication.test.ts
  • greenfield/scripts/delivery/provisioning/host-operations/60-mira-dashboard-host-operations.rules
  • greenfield/scripts/delivery/provisioning/host-operations/README.md
  • greenfield/scripts/delivery/provisioning/host-operations/hostOperationsProvisioningFilesystem.ts
  • greenfield/scripts/delivery/provisioning/host-operations/installHostOperationsProvisioning.ts
  • greenfield/scripts/delivery/provisioning/host-operations/mira-dashboard-deferred-reboot.service
  • greenfield/scripts/delivery/provisioning/host-operations/mira-dashboard-deferred-reboot.timer
  • greenfield/scripts/delivery/provisioning/host-operations/mira-dashboard-host-operation
  • greenfield/scripts/delivery/provisioning/host-operations/mira-dashboard-host-system-cleanup.service
  • greenfield/scripts/delivery/provisioning/host-operations/mira-dashboard-host-system-restart.service
  • greenfield/scripts/delivery/provisioning/host-operations/mira-dashboard-host-system-update.service
  • greenfield/scripts/delivery/provisioning/host-operations/policy.ts
  • greenfield/scripts/delivery/releaseIdentity.test.ts
  • greenfield/scripts/delivery/releaseIdentity.ts
  • greenfield/scripts/delivery/releaseStaging.ts
  • greenfield/scripts/development/developmentFrontend.test.ts
  • greenfield/scripts/development/developmentMigrationIdentity.test.ts
  • greenfield/scripts/development/developmentMigrationIdentity.ts
  • greenfield/scripts/development/developmentRuntime.test.ts
  • greenfield/scripts/development/developmentRuntime.ts
  • greenfield/scripts/development/developmentState.ts
  • greenfield/scripts/development/tanStackRouterHmrWorkaroundPlugin.test.ts
  • greenfield/scripts/development/tanStackRouterHmrWorkaroundPlugin.ts
  • greenfield/scripts/documentation/jsonSchema.test.ts
  • greenfield/scripts/documentation/jsonSchema.ts
  • greenfield/scripts/sourceBoundaries/policy.test.ts
  • greenfield/scripts/testSupport/productionDeliveryFixture.ts
  • greenfield/src/app/dashboardServer.test.ts
  • greenfield/src/app/dashboardServer.ts
  • greenfield/src/app/developmentWorker.ts
  • greenfield/src/app/worker.test.ts
  • greenfield/src/app/worker.ts
  • greenfield/src/browser/jobs/JobsRoute.test.tsx
  • greenfield/src/browser/jobs/JobsRoute.tsx
  • greenfield/src/browser/overview/OverviewRoute.test.tsx
  • greenfield/src/browser/overview/OverviewServiceActionsCard.tsx
  • greenfield/src/browser/overview/OverviewServiceActionsSection.test.tsx
  • greenfield/src/browser/overview/OverviewServiceActionsSection.tsx
  • greenfield/src/browser/overview/serviceActionsOperations.test.ts
  • greenfield/src/browser/overview/serviceActionsOperations.ts
  • greenfield/src/contracts/serviceActions.test.ts
  • greenfield/src/contracts/serviceActions.ts
  • greenfield/src/server/database/migrations/jobsSchema.test.ts
  • greenfield/src/server/database/migrations/migrationGraph.test.ts
  • greenfield/src/server/database/schema/checks.ts
  • greenfield/src/server/database/schema/drizzleSchema.ts
  • greenfield/src/server/database/schema/hostRestartClaimFence.ts
  • greenfield/src/server/database/schema/jobRuns.ts
  • greenfield/src/server/database/validation/hostRestartClaimFence.ts
  • greenfield/src/server/database/validation/jobRuns.ts
  • greenfield/src/server/database/validation/rowSchemas.test.ts
  • greenfield/src/server/domains/cache/repository.test.ts
  • greenfield/src/server/domains/files/jobScheduler.test.ts
  • greenfield/src/server/domains/jobs/actionExecutors.test.ts
  • greenfield/src/server/domains/jobs/actionExecutors.ts
  • greenfield/src/server/domains/jobs/actionRegistry.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/jobs/coordinator.ts
  • greenfield/src/server/domains/jobs/logMaintenanceQueue.test.ts
  • greenfield/src/server/domains/jobs/records.ts
  • greenfield/src/server/domains/jobs/repository.test.ts
  • greenfield/src/server/domains/jobs/repository.ts
  • greenfield/src/server/domains/jobs/service.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.ts
  • greenfield/src/server/domains/jobs/workerRuntime.test.ts
  • greenfield/src/server/domains/jobs/workerRuntime.ts
  • greenfield/src/server/domains/jobs/workerSystem.test.ts
  • greenfield/src/server/domains/openClawSettings/restartQueue.test.ts
  • greenfield/src/server/domains/serviceActions/procedures.test.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
  • greenfield/src/server/domains/serviceActions/statusReader.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayProtocol.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayProtocol.ts
  • greenfield/src/shared/databaseMigrationManifest.ts
  • greenfield/src/shared/hostOperations.ts
  • greenfield/src/shared/linuxBootIdentity.ts
  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
  • greenfield/src/test/parity/fixtures/legacy-endpoints.json
  • greenfield/src/test/parity/parityInventory.test.ts
  • greenfield/src/worker/system/fixedHostOperationsBroker.test.ts
  • greenfield/src/worker/system/fixedHostOperationsBroker.ts
  • greenfield/src/worker/system/linuxBootIdentity.ts
  • greenfield/src/worker/system/systemHostOperationsProvisioning.test.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 669497a5-c374-40e8-9fb2-2dd65f99c45f

📥 Commits

Reviewing files that changed from the base of the PR and between dacc366 and eb71e93.

📒 Files selected for processing (32)
  • greenfield/migrations/20260804022252_dashboard-foundation/migration.sql
  • greenfield/migrations/20260804022252_dashboard-foundation/snapshot.json
  • greenfield/scripts/audits/openclaw/sourceAudit.ts
  • greenfield/src/browser/overview/OverviewServiceActionsCard.tsx
  • greenfield/src/browser/overview/OverviewServiceActionsSection.test.tsx
  • greenfield/src/browser/overview/OverviewServiceActionsSection.tsx
  • greenfield/src/browser/overview/serviceActionsOperations.test.ts
  • greenfield/src/browser/overview/serviceActionsOperations.ts
  • greenfield/src/server/database/migrations/migrationGraph.test.ts
  • greenfield/src/server/database/schema/jobChecks.ts
  • greenfield/src/server/database/schema/workerInstances.ts
  • greenfield/src/server/database/validation/rowSchemas.test.ts
  • greenfield/src/server/database/validation/workerInstances.ts
  • greenfield/src/server/domains/jobs/actionExecutors.test.ts
  • greenfield/src/server/domains/jobs/actionExecutors.ts
  • greenfield/src/server/domains/jobs/actionRegistry.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/jobs/coordinator.ts
  • greenfield/src/server/domains/jobs/repository.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
  • greenfield/src/server/domains/serviceActions/service.ts
  • greenfield/src/server/domains/serviceActions/statusReader.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayOpenClawServiceActionsProvider.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayProtocol.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayProtocol.ts
  • greenfield/src/server/platform/observability/structuredLogger.test.ts
  • greenfield/src/server/platform/observability/structuredLogger.ts
  • greenfield/src/shared/databaseMigrationManifest.ts
  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
🚧 Files skipped from review as they are similar to previous changes (23)
  • greenfield/src/shared/databaseMigrationManifest.ts
  • greenfield/src/server/platform/observability/structuredLogger.test.ts
  • greenfield/src/server/database/migrations/migrationGraph.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.test.ts
  • greenfield/src/server/database/validation/rowSchemas.test.ts
  • greenfield/src/browser/overview/serviceActionsOperations.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayProtocol.ts
  • greenfield/src/server/database/schema/jobChecks.ts
  • greenfield/migrations/20260804022252_dashboard-foundation/snapshot.json
  • greenfield/src/server/domains/jobs/actionExecutors.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayProtocol.test.ts
  • greenfield/src/server/domains/jobs/coordinator.ts
  • greenfield/src/server/platform/gateway/persistentGatewayOpenClawServiceActionsProvider.test.ts
  • greenfield/src/server/platform/observability/structuredLogger.ts
  • greenfield/src/browser/overview/serviceActionsOperations.ts
  • greenfield/scripts/audits/openclaw/sourceAudit.ts
  • greenfield/src/browser/overview/OverviewServiceActionsCard.tsx
  • greenfield/src/server/domains/serviceActions/service.ts
  • greenfield/src/server/domains/serviceActions/statusReader.test.ts
  • greenfield/src/server/database/validation/workerInstances.ts
  • greenfield/src/server/domains/jobs/actionExecutors.ts
  • greenfield/src/server/domains/jobs/repository.ts
  • greenfield/src/server/database/schema/workerInstances.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Analyze JavaScript and TypeScript
  • GitHub Check: storybook
  • GitHub Check: dashboard-checks
🧰 Additional context used
🧠 Learnings (16)
📓 Common learnings
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 341
File: backend/src/services/pullRequests.ts:2854-2854
Timestamp: 2026-07-27T16:39:39.445Z
Learning: In `backend/src/services/pullRequests.ts`, direct calls to `cleanupClosedPullRequestPreview(number)` from `approvePullRequest` and `rejectPullRequest` are intentional: their `github.merge`, `github.merge-deploy`, and `github.reject` scheduled actions are exclusive and share the globally single-capacity executor with `dashboard.preview.*` lifecycle actions. Enqueuing and awaiting a nested preview-cleanup job from these actions would deadlock the worker.
📚 Learning: 2026-08-07T18:47:59.017Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 398
File: greenfield/src/server/domains/monitoring/routeEffects.ts:21-63
Timestamp: 2026-08-07T18:47:59.017Z
Learning: In the Greenfield TypeScript application, `greenfield/package.json` and `greenfield/bun.lock` pin `effect` to `4.0.0-beta.104`. In this version, `Effect.runPromise` rejects with the original typed domain-error instance, so `instanceof` checks in `greenfield/src/server/domains/monitoring/routeEffects.ts` remain valid. The route-level assertions in `greenfield/src/server/domains/monitoring/procedures.test.ts` cover the monitoring tRPC mappings, including `BAD_REQUEST`, `CONFLICT`, `NOT_FOUND`, and `PRECONDITION_FAILED`.

Applied to files:

  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
📚 Learning: 2026-08-08T02:53:11.841Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 401
File: greenfield/src/server/domains/jobs/routes.ts:29-56
Timestamp: 2026-08-08T02:53:11.841Z
Learning: In `greenfield/src/server/domains/jobs/routes.ts`, with the pinned `effect` version `4.0.0-beta.104`, `Effect.runPromise` preserves typed domain error instances for `JobNotFoundError`, `JobConflictError`, and `JobValidationError`. The existing `runJobEffect` `instanceof` checks correctly map these failures to `NOT_FOUND`, `CONFLICT`, and `BAD_REQUEST`.

Applied to files:

  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.ts
📚 Learning: 2026-08-08T02:53:28.998Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 401
File: greenfield/src/server/domains/jobs/coordinator.ts:506-517
Timestamp: 2026-08-08T02:53:28.998Z
Learning: In the TypeScript durable jobs domain, `greenfield/src/server/domains/jobs/repository.ts` validates every SQLite `JobRunRecord` through `jobRunSelectSchema` before it returns the record to `greenfield/src/server/domains/jobs/coordinator.ts`. `greenfield/src/server/database/validation/jobRuns.ts` validates `payloadJson` against the byte limit and `jobPayloadSchema`, and `greenfield/src/shared/json.ts` `parseJsonText` returns `undefined` instead of throwing for invalid JSON. Therefore, `executeClaim` only receives schema-valid persisted payloads in the production SQLite repository.

Applied to files:

  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
📚 Learning: 2026-08-07T18:48:18.623Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 398
File: greenfield/src/server/database/validation/notifications.ts:48-49
Timestamp: 2026-08-07T18:48:18.623Z
Learning: In `greenfield/src/server/database/validation/notifications.ts`, Drizzle Valibot generated notification schemas retain nullable and optional behavior for the `reportId: uuidV7TextSchema` and `source: () => monitoringReportSourceSchema` refinements. Regression tests in `greenfield/src/server/database/validation/notifications.test.ts` cover `null` values for both fields in insert and select schemas, plus omission of both fields in the insert schema.

Applied to files:

  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
📚 Learning: 2026-08-07T17:05:34.083Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 397
File: greenfield/src/server/domains/agents/routes.ts:19-32
Timestamp: 2026-08-07T17:05:34.083Z
Learning: In `greenfield/src/server/domains/agents/routes.ts`, with the installed `effect4.0.0-beta.104`, `Effect.runPromise(Effect.fail(error))` rejects with the original typed error object. Therefore `runAgentEffect` can map `AgentNotFoundError` with `error instanceof AgentNotFoundError`; `greenfield/src/server/domains/agents/procedures.test.ts` covers the unknown-agent to `NOT_FOUND` boundary.

Applied to files:

  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
📚 Learning: 2026-08-08T02:53:11.767Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 401
File: greenfield/src/contracts/jobModel.ts:495-505
Timestamp: 2026-08-08T02:53:11.767Z
Learning: In the durable jobs platform, `schedules.run` creates a `triggerType: "manual"` job run with `scheduledJobId` and `scheduledJobVersion` provenance. In `greenfield/src/contracts/jobModel.ts`, `jobRunSummaryIsConsistent` intentionally requires schedule identity for these manual runs. In `greenfield/src/server/domains/jobs/repository.ts`, this provenance supports schedule run history and one-active-run-per-schedule enforcement.

Applied to files:

  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.ts
📚 Learning: 2026-08-07T17:05:36.638Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 397
File: greenfield/src/server/domains/agents/service.test.ts:225-239
Timestamp: 2026-08-07T17:05:36.638Z
Learning: In Bun test files, write rejection assertions as `expect(promise).rejects...` without `await`. The repository's installed matcher types return `void`, and ESLint's `typescript(await-thenable)` rule rejects awaiting these matcher assertions.

Applied to files:

  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
📚 Learning: 2026-08-07T18:47:49.639Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 398
File: greenfield/src/server/domains/monitoring/catalogErrors.ts:3-3
Timestamp: 2026-08-07T18:47:49.639Z
Learning: In the greenfield TypeScript application, use the pinned Effect version 4.0.0-beta.104 API. Preserve `Schema.Literals` for readonly literal tuples and arrays, and do not replace it with variadic `Schema.Literal(...)` unless the replacement has been validated against the pinned Effect version.

Applied to files:

  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
📚 Learning: 2026-08-12T04:22:28.232Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 421
File: greenfield/src/app/dashboardServer.ts:734-753
Timestamp: 2026-08-12T04:22:28.232Z
Learning: In `greenfield/src/server/platform/files/openClawFileRootConfiguration.ts`, the reviewed `openclaw-config` root intentionally remains non-writable while its fixed manifest permits replacement of only `openclaw.json` and `hooks/transforms/agentmail.ts`. `openclaw.json` replacement requires the existing actor-bound secret-reveal and CAS revision controls. The OpenClaw configuration backup is independently restricted to the exact `openclaw-config/openclaw.json` locator.

Applied to files:

  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.ts
📚 Learning: 2026-07-22T14:45:35.974Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 0
File: :0-0
Timestamp: 2026-07-22T14:45:35.974Z
Learning: In `src/components/features/chat/transport/openClawRuntimeAdapter.ts`, media on a Synthetic `toolUse` assistant turn is provider-turn-scoped rather than tool-call-scoped. When one turn contains multiple tool calls, exactly one sibling tool draft must own the media to preserve it without rendering duplicate images or attachments. `src/test/openClawAdapterVariants.test.ts` covers this behavior in the `owns turn-scoped Synthetic media once across multiple tool drafts` regression.

Applied to files:

  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
📚 Learning: 2026-08-07T18:47:51.240Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 398
File: greenfield/src/contracts/reports.ts:175-179
Timestamp: 2026-08-07T18:47:51.240Z
Learning: In the greenfield monitoring domain, `reports.upsert` intentionally permits both scoped session principals and automation principals with the `reports:write` capability. `greenfield/src/server/domains/monitoring/procedures.test.ts` verifies session upserts, and generated procedure documentation records the endpoint as `Authenticated: reports:write`. In contrast, `notifications.upsert` is intentionally restricted to automation principals.

Applied to files:

  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
📚 Learning: 2026-08-01T06:32:15.434Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 365
File: backend/src/gateway.ts:1727-1736
Timestamp: 2026-08-01T06:32:15.434Z
Learning: For `backend/src/gateway.ts`, installed OpenClaw v2026.6.11 accepts only `sessionKey`, `agentId`, `message`, and `label` in the public `chat.inject` schema. It rejects unknown properties such as `idempotencyKey`. The Dashboard task notification flow does not retry `sendSessionControlEvent` after a partial inject-then-wake failure; it logs the failure and keeps the durable control notice visible.

Applied to files:

  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
📚 Learning: 2026-07-14T11:31:42.796Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 277
File: src/test/pageBehavior.test.tsx:1887-1912
Timestamp: 2026-07-14T11:31:42.796Z
Learning: In `src/test/pageBehavior.test.tsx` (Bun test suite for Mira Dashboard pages), test-local overrides of `globalThis.fetch` via `Object.defineProperty` do not need their own `try/finally` restoration. The suite's `afterEach` hook unconditionally restores `globalThis.fetch` to `originalGlobals.fetch` (and resets WebSocket, requestAnimationFrame, cancelAnimationFrame), and `beforeEach` installs a fresh fetch mock before every test, so isolation is already guaranteed even if a test throws.

Applied to files:

  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
  • greenfield/src/browser/overview/OverviewServiceActionsSection.test.tsx
📚 Learning: 2026-08-06T11:55:49.248Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 392
File: tsconfig.worker.json:7-12
Timestamp: 2026-08-06T11:55:49.248Z
Learning: In `tsconfig.worker.json`, do not include `backend/src/services/jobExecutionQueue/worker.ts`. This legacy backend worker is outside the greenfield ownership boundary. No greenfield worker production root exists yet. Future `src/app/worker` variants and `src/worker` sources are covered by the worker TypeScript graph and source-boundary gate.

Applied to files:

  • greenfield/src/server/domains/jobs/coordinator.test.ts
📚 Learning: 2026-08-08T14:26:06.566Z
Learnt from: mira-2026
Repo: rajohan/Mira-Dashboard PR: 403
File: greenfield/migrations/20260804022252_dashboard-foundation/snapshot.json:4-4
Timestamp: 2026-08-08T14:26:06.566Z
Learning: In the `greenfield/` future root, `greenfield/migrations/20260804022252_dashboard-foundation` is an unpublished foundation baseline. It has not been applied by deployed Dashboard environments. The Greenfield cutover creates a fresh database from the final reviewed baseline, and applied copies are disposable test evidence. Therefore, the foundation migration and its `snapshot.json` can be intentionally evolved in place before publication; do not require successor migrations solely to preserve pre-publication migration checksums.

Applied to files:

  • greenfield/migrations/20260804022252_dashboard-foundation/migration.sql
🔇 Additional comments (9)
greenfield/migrations/20260804022252_dashboard-foundation/migration.sql (1)

142-142: LGTM!

Also applies to: 1001-1001, 1087-1097, 1813-1837, 1980-2001, 2146-2156

greenfield/src/browser/overview/OverviewServiceActionsSection.test.tsx (1)

11-30: LGTM!

Also applies to: 138-145, 212-297, 344-365, 453-461, 519-519

greenfield/src/browser/overview/OverviewServiceActionsSection.tsx (1)

1-70: LGTM!

Also applies to: 72-153, 156-207

greenfield/src/server/domains/jobs/actionRegistry.ts (1)

47-114: LGTM!

Also applies to: 156-163, 471-525

greenfield/src/server/domains/jobs/coordinator.test.ts (1)

12-12: LGTM!

Also applies to: 84-84, 272-272, 389-389, 437-437, 502-530, 757-757, 831-831, 1871-1899

greenfield/src/server/domains/jobs/serviceActionQueue.test.ts (1)

1-135: LGTM!

Also applies to: 137-190, 193-232, 234-301, 303-338, 340-410, 412-445

greenfield/src/server/domains/jobs/serviceActionQueue.ts (1)

1-86: LGTM!

Also applies to: 88-121, 123-151, 153-186, 187-205, 207-276, 278-333

greenfield/src/server/domains/serviceActions/service.test.ts (1)

349-371: LGTM!

greenfield/src/test/integration/openclaw/sourceAudit.test.ts (1)

4043-4077: LGTM!


📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added dashboard Service Actions for OpenClaw session cleanup and installation updates, including status, queueing, recovery, and job links.
    • Added fixed host restart and update actions, currently unavailable until additional safeguards are implemented.
    • Added idempotent requests, recent-MFA authorization, audit tracking, and worker capability reporting.
  • Security

    • Replaced generic synchronous command execution with controlled, allowlisted operations and fail-closed availability checks.
  • Documentation

    • Updated architecture, security, deployment, implementation, and progress documentation.

<hidden_range_assignment>
<range_id>range_aeea9a615422</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_5640751fb1a9</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_36b9f02311f0</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_7000cd18f466</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_f36b4bfe078e</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_36fbadd684cd</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>openclaw-boundary</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_a8cb01527e09</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_f992cba7fc0e</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>openclaw-boundary</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_83002fec0efc</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>openclaw-boundary</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_d908e22292b1</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>openclaw-boundary</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_603ea7b5f42e</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_111da1cd0ed9</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_3b3fa26736de</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_96a19e70e34c</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_f62db548119f</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_d16b83b17d5d</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_f95d2f273319</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>durable-queue-workers</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_6f9161af3a3d</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>service-api</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_ca2c9f2a08da</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>service-api</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_1dd042242a62</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>openclaw-boundary</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_0fae49653c19</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>openclaw-boundary</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_71f77c3287e7</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>openclaw-boundary</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_e99eb4c8a968</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>openclaw-boundary</layer_id>
</hidden_range_assignment>

<hidden_range_assignment>
<range_id>range_af55fe8add23</range_id>
<cohort_id>service-actions</cohort_id>
<layer_id>audit-docs-parity</layer_id>
</hidden_range_assignment>

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly identifies the main change: replacing generic exec behavior with Service Actions.
Description check ✅ Passed The description thoroughly explains the change, security model, availability boundary, parity impact, and verification results, despite not copying every template heading.

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: 8

🧹 Nitpick comments (10)
greenfield/src/server/domains/serviceActions/service.ts (1)

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

Preserve ServiceActionsServiceError reasons in the failure mapping.

The final else branch wraps every non-queue, non-validation error in a new unavailable error. A ServiceActionsServiceError raised inside authorizeDispatch therefore loses its reason, and the settlement classification at lines 296-299 can change from partial to failed. Today the only such error already uses unavailable, so behavior is unchanged. Add a passthrough branch to keep the mapping stable if another reason is thrown later, and to match getStatus at line 223.

♻️ Proposed passthrough branch
             let mapped: unknown;
-            if (error instanceof ServiceActionQueueError) {
+            if (error instanceof ServiceActionsServiceError) {
+                mapped = error;
+            } else if (error instanceof ServiceActionQueueError) {
                 mapped = queueFailure(error);
             } else if (error instanceof v.ValiError) {
🤖 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 `@greenfield/src/server/domains/serviceActions/service.ts` around lines 281 -
301, Update the failure mapping around authorizeDispatch to add a passthrough
branch for existing ServiceActionsServiceError instances before the generic
unavailable wrapping. Preserve each error’s original reason so settleAudit
retains the correct partial or failed classification, while leaving queue and
validation error handling unchanged.
greenfield/src/server/platform/observability/structuredLogger.ts (1)

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

Derive accepted action IDs from the canonical inventory.

Import serviceActionIds from greenfield/src/contracts/serviceActions.ts and use a ReadonlySet<ServiceActionId> for the fields.actionId guard. This keeps audit-settlement logging aligned with future ServiceActionId values.

🤖 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 `@greenfield/src/server/platform/observability/structuredLogger.ts` around
lines 387 - 404, Update the service-actions-audit-settlement validation in the
structured logger to import the canonical serviceActionIds inventory and use a
ReadonlySet<ServiceActionId> for validating fields.actionId, replacing the
hardcoded action ID comparisons while preserving the existing eventName and
settlement checks.
greenfield/src/server/domains/jobs/actionExecutors.test.ts (1)

80-81: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Consider asserting that host action keys stay unregistered.

This resolver fixture supplies openClawServiceActions but not hostOperations. greenfield/docs/architecture/greenfield-rewrite/runtime-and-delivery.md lines 429-430 state that the worker must not advertise the host action keys until a distinct worker OS identity exists. A negative assertion locks that gate into the test suite.

♻️ Proposed addition
         expect(findAction("openclaw.sessions.cleanup")).toBeDefined();
         expect(findAction("openclaw.installation.update")).toBeDefined();
+        expect(findAction("host.system.restart")).toBeUndefined();
+        expect(findAction("host.system.update")).toBeUndefined();
🤖 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 `@greenfield/src/server/domains/jobs/actionExecutors.test.ts` around lines 80 -
81, Extend the resolver test around findAction to assert that the host action
keys are not registered when only openClawServiceActions is supplied and
hostOperations is absent. Preserve the existing positive assertions for the
OpenClaw service actions and verify the worker does not advertise the
host-operation keys.
greenfield/src/server/domains/jobs/actionExecutors.ts (2)

342-345: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse the exported HostOperationId alias in the signature.

Line 57 defines HostOperationId as exactly "system-restart" | "system-update". The parameter restates that union. Reusing the alias keeps the two in step if the inventory changes.

♻️ Proposed refactor
 export function createHostOperationJobExecutor(
     hostOperations: FixedHostOperationsExecutionPort,
-    operationId: "system-restart" | "system-update"
+    operationId: HostOperationId
 ): JobActionExecutor {
🤖 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 `@greenfield/src/server/domains/jobs/actionExecutors.ts` around lines 342 -
345, Update createHostOperationJobExecutor to use the exported HostOperationId
alias for its operationId parameter instead of restating the string-literal
union, preserving the existing type contract while keeping it synchronized with
the alias.

560-611: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider collapsing the four conditional executor blocks into one helper.

The four blocks repeat the same shape: check that the authority exists, check that a matching definition is present, then emit one frozen entry. A small local helper removes about 40 lines and makes the gating rule explicit in one place.

♻️ Proposed refactor sketch
+    const registeredKeys = new Set(definitions.map(({ actionKey }) => actionKey));
+    const gatedExecutor = (
+        actionKey: string,
+        execute: JobActionExecutor | undefined
+    ) =>
+        execute === undefined || !registeredKeys.has(actionKey)
+            ? []
+            : [Object.freeze({ actionKey, execute })];

Then each site becomes one call, for example:

...gatedExecutor(
    openClawSessionsCleanupJobActionKey,
    dependencies.openClawServiceActions === undefined
        ? undefined
        : createOpenClawServiceActionJobExecutor(
              dependencies.openClawServiceActions,
              "openclaw-cleanup"
          )
),
🤖 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 `@greenfield/src/server/domains/jobs/actionExecutors.ts` around lines 560 -
611, Collapse the repeated conditional executor entries in the surrounding
action-executor construction into a local gatedExecutor helper. Have it accept
an action key and optional executor, return no entry when the executor is
undefined or definitions lacks the key, and otherwise return one frozen entry;
replace the four blocks for the OpenClaw cleanup, OpenClaw update, system
restart, and system update action keys with helper calls while preserving their
existing executor factories and operation names.
greenfield/src/server/domains/jobs/repository.ts (1)

2590-2611: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Two small clarity items in #failQueuedRun.

Line 2611 calls parseRun(...) and discards the result. The parallel #cancelQueuedRun at line 2573 calls requiredRow(...) alone. If the parse is intentional row validation, keep it and add a short comment. Otherwise drop it for symmetry.

The parameter type is ScheduleQueuedCancellation, but this method records a failure and never writes cancel metadata. A shared name such as ScheduleQueuedTermination describes both call sites.

♻️ Proposed refactor for line 2611
-        parseRun(requiredRow(row, "queued run failure"));
+        requiredRow(row, "queued run failure");
🤖 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 `@greenfield/src/server/domains/jobs/repository.ts` around lines 2590 - 2611,
Update `#failQueuedRun` for clarity: either retain parseRun validation with a
brief comment explaining the intentionally discarded result, or remove it to
match `#cancelQueuedRun`. Rename the shared ScheduleQueuedCancellation type to
ScheduleQueuedTermination and update both call sites and references while
preserving behavior.
greenfield/src/server/domains/jobs/serviceActionQueue.test.ts (1)

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

Assert the active-run rejection and the resource locks.

This is the only test that inspects the enqueue input. Two safety properties of the queue are not covered: rejectWhenActionActive: true, which enforces one active run per action key, and resourceKeysJson, which carries the fixed exclusive locks. Both are cheap to pin here.

💚 Proposed additions
+            expect(fixture.enqueues[0]?.rejectWhenActionActive).toBe(true);
             expect(fixture.enqueues[0]?.run).toMatchObject({
                 actionKey: serviceActionJobActionKeys[actionId],
                 attemptLimit: 1,
                 cancellationPolicy: "never",
                 idempotencyKey,
                 payloadJson: "{}",
                 requestedById: actor.id,
                 requestedByKind: "user",
                 resourceClass: "exclusive",
+                resourceKeysJson: JSON.stringify(definitions[actionId].resourceKeys),
                 retrySafe: false,
                 triggerType: "manual",
             });
🤖 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 `@greenfield/src/server/domains/jobs/serviceActionQueue.test.ts` around lines
150 - 161, Extend the enqueue input assertion in the service action queue test
to verify rejectWhenActionActive is true and resourceKeysJson contains the
expected fixed exclusive locks, alongside the existing action configuration
fields. Use the fixture’s established expected resource-key values and preserve
the current match structure.
greenfield/src/server/domains/jobs/actionRegistry.ts (1)

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

Add explicit validation messages to both OpenClaw result status schemas.

Use "OpenClaw cleanup result is invalid" for v.literal("completed") and "OpenClaw update result is invalid" for v.picklist(["accepted", "completed"]). Valibot 1.4.2 supports the second message argument for both APIs.

🤖 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 `@greenfield/src/server/domains/jobs/actionRegistry.ts` at line 103, Update
both OpenClaw result status schemas: pass “OpenClaw cleanup result is invalid”
as the second argument to the v.literal("completed") call, and “OpenClaw update
result is invalid” as the second argument to the v.picklist(["accepted",
"completed"]) call.
greenfield/src/server/domains/jobs/serviceActionQueue.ts (1)

99-118: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pin the fixed Service Action policy at composition time.

validateJobUnscheduledActionDefinition already enforces valid attempt limits, cancellation policies, boolean retrySafe, and canonical unique ascending resourceKeys. prepareDefinitions still accepts valid but unsafe policy values. Since enqueue copies these values directly into job_runs, require attemptLimit === 1, retrySafe === false, and cancellationPolicy === "never". Do not duplicate the resourceKeys ordering check; the validator already rejects descending keys.

🤖 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 `@greenfield/src/server/domains/jobs/serviceActionQueue.ts` around lines 99 -
118, Update prepareDefinitions to enforce the fixed Service Action policy after
validation: require attemptLimit === 1, retrySafe === false, and
cancellationPolicy === "never" alongside the existing actionKey and
manualExposure checks. Keep the validator responsible for resourceKeys ordering
and do not duplicate that validation.
greenfield/src/server/platform/gateway/persistentGatewayOpenClawServiceActionsProvider.test.ts (1)

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

This assertion cannot fail.

JSON.stringify on an Error instance serializes only own enumerable properties. message and name are not enumerable, so the result is {"reason":"unknown-outcome"}. The check for "systemctl" therefore proves nothing about sanitization.

Assert against the concatenated name, message, and stack, or drop the check.

♻️ Proposed refactor
-        expect(JSON.stringify(unknownFailure)).not.toContain("systemctl");
+        expect(
+            `${String((unknownFailure as Error).name)} ${String((unknownFailure as Error).message)}`
+        ).not.toContain("systemctl");
🤖 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
`@greenfield/src/server/platform/gateway/persistentGatewayOpenClawServiceActionsProvider.test.ts`
at line 157, Update the assertion for unknownFailure in the relevant test so it
checks the concatenated Error name, message, and stack rather than
JSON.stringify(unknownFailure); retain the existing expectation that this
combined error representation does not contain "systemctl".
🤖 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 `@greenfield/scripts/audits/openclaw/sourceAudit.ts`:
- Around line 3114-3140: Add an order-sensitive check in the cleanup execution
audit after assertRequiredMarkers: locate the indexes of the lifecycle
maintenance call and enforceSqliteSessionHistoryDiskBudget call, and throw if
the disk-budget call occurs before entry maintenance. Keep the existing marker
assertions unchanged and ensure the check enforces disk-budget execution after
applySqliteSessionEntryLifecycleMutation.

In `@greenfield/src/browser/overview/OverviewServiceActionsCard.tsx`:
- Around line 109-111: Add a retryLabel field to ServiceActionPresentation and
provide explicitly cased retry labels for all four service actions, including
“OpenClaw” branding. Update OverviewServiceActionsCard to render
presentation.retryLabel instead of lowercasing actionLabel, and adjust the
corresponding button-name assertions in OverviewServiceActionsSection tests.

In `@greenfield/src/server/database/schema/workerInstances.ts`:
- Around line 27-30: Update the worker_instances table constraints around
workerActionKeysJson to add a SQLite JSON array-length check enforcing
workerActionKeyMaximum, while retaining the existing boundedJsonArrayCheck for
syntax and byte-size validation.

In `@greenfield/src/server/database/validation/workerInstances.ts`:
- Around line 83-93: Update the workerActionKeysJsonSchema validation to enforce
the raw stored value’s byte limit before parsing, then parse it and require the
input value to exactly equal JSON.stringify(parsed), rejecting trailing
whitespace and other noncanonical encodings while preserving the existing
invalid-value message.

In `@greenfield/src/server/domains/jobs/actionExecutors.test.ts`:
- Line 236: Update both redaction assertions in the action executor test to
inspect the error’s textual representation with String(failure) instead of
JSON.stringify(failure), matching serviceActionQueue.test.ts and ensuring
embedded private paths or Gateway details are actually checked.

In `@greenfield/src/server/domains/jobs/coordinator.ts`:
- Around line 787-789: Update the action key registration near executeClaim to
advertise only keys executable by findAction, rather than mapping every
actionDefinitions entry. Reuse the same executable registrations that findAction
resolves, or filter definitions through findAction before calling
serializeWorkerActionKeys, while preserving the existing serialization flow.

In `@greenfield/src/server/domains/serviceActions/statusReader.test.ts`:
- Around line 125-141: Update the abort test around reader.read so it tracks
calls to both readActionPayloadRunSnapshots and readWorkerActionAvailability,
then assert each was not called after the already-aborted signal causes the
"request closed" failure. Keep the existing error assertions unchanged.

In `@greenfield/src/server/platform/gateway/persistentGatewayProtocol.ts`:
- Around line 1503-1512: Update the status mapping in the response parser so any
parsed.output.handoff with status "started" produces "accepted", regardless of
parsed.output.result.status. Preserve "completed" for successful results and
"failed" for other responses, and update the existing test expectation for
started handoffs.

---

Nitpick comments:
In `@greenfield/src/server/domains/jobs/actionExecutors.test.ts`:
- Around line 80-81: Extend the resolver test around findAction to assert that
the host action keys are not registered when only openClawServiceActions is
supplied and hostOperations is absent. Preserve the existing positive assertions
for the OpenClaw service actions and verify the worker does not advertise the
host-operation keys.

In `@greenfield/src/server/domains/jobs/actionExecutors.ts`:
- Around line 342-345: Update createHostOperationJobExecutor to use the exported
HostOperationId alias for its operationId parameter instead of restating the
string-literal union, preserving the existing type contract while keeping it
synchronized with the alias.
- Around line 560-611: Collapse the repeated conditional executor entries in the
surrounding action-executor construction into a local gatedExecutor helper. Have
it accept an action key and optional executor, return no entry when the executor
is undefined or definitions lacks the key, and otherwise return one frozen
entry; replace the four blocks for the OpenClaw cleanup, OpenClaw update, system
restart, and system update action keys with helper calls while preserving their
existing executor factories and operation names.

In `@greenfield/src/server/domains/jobs/actionRegistry.ts`:
- Line 103: Update both OpenClaw result status schemas: pass “OpenClaw cleanup
result is invalid” as the second argument to the v.literal("completed") call,
and “OpenClaw update result is invalid” as the second argument to the
v.picklist(["accepted", "completed"]) call.

In `@greenfield/src/server/domains/jobs/repository.ts`:
- Around line 2590-2611: Update `#failQueuedRun` for clarity: either retain
parseRun validation with a brief comment explaining the intentionally discarded
result, or remove it to match `#cancelQueuedRun`. Rename the shared
ScheduleQueuedCancellation type to ScheduleQueuedTermination and update both
call sites and references while preserving behavior.

In `@greenfield/src/server/domains/jobs/serviceActionQueue.test.ts`:
- Around line 150-161: Extend the enqueue input assertion in the service action
queue test to verify rejectWhenActionActive is true and resourceKeysJson
contains the expected fixed exclusive locks, alongside the existing action
configuration fields. Use the fixture’s established expected resource-key values
and preserve the current match structure.

In `@greenfield/src/server/domains/jobs/serviceActionQueue.ts`:
- Around line 99-118: Update prepareDefinitions to enforce the fixed Service
Action policy after validation: require attemptLimit === 1, retrySafe === false,
and cancellationPolicy === "never" alongside the existing actionKey and
manualExposure checks. Keep the validator responsible for resourceKeys ordering
and do not duplicate that validation.

In `@greenfield/src/server/domains/serviceActions/service.ts`:
- Around line 281-301: Update the failure mapping around authorizeDispatch to
add a passthrough branch for existing ServiceActionsServiceError instances
before the generic unavailable wrapping. Preserve each error’s original reason
so settleAudit retains the correct partial or failed classification, while
leaving queue and validation error handling unchanged.

In
`@greenfield/src/server/platform/gateway/persistentGatewayOpenClawServiceActionsProvider.test.ts`:
- Line 157: Update the assertion for unknownFailure in the relevant test so it
checks the concatenated Error name, message, and stack rather than
JSON.stringify(unknownFailure); retain the existing expectation that this
combined error representation does not contain "systemctl".

In `@greenfield/src/server/platform/observability/structuredLogger.ts`:
- Around line 387-404: Update the service-actions-audit-settlement validation in
the structured logger to import the canonical serviceActionIds inventory and use
a ReadonlySet<ServiceActionId> for validating fields.actionId, replacing the
hardcoded action ID comparisons while preserving the existing eventName and
settlement checks.
🪄 Autofix

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: e87793e1-5f9e-4233-b178-bae3df03b680

📥 Commits

Reviewing files that changed from the base of the PR and between 54836ec and dacc366.

⛔ Files ignored due to path filters (12)
  • greenfield/docs/generated/procedures.md is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/automationSecurity.createPrincipal.input.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/automationSecurity.createPrincipal.output.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/automationSecurity.disablePrincipal.output.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/automationSecurity.listPrincipals.output.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/automationSecurity.replaceCapabilities.input.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/automationSecurity.replaceCapabilities.output.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/securityAudit.listEvents.output.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/serviceActions.getStatus.input.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/serviceActions.getStatus.output.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/serviceActions.request.input.schema.json is excluded by !**/generated/** and included by **/*
  • greenfield/docs/generated/schemas/serviceActions.request.output.schema.json is excluded by !**/generated/** and included by **/*
📒 Files selected for processing (88)
  • greenfield/docs/architecture/greenfield-rewrite/application-architecture.md
  • greenfield/docs/architecture/greenfield-rewrite/data-and-security.md
  • greenfield/docs/architecture/greenfield-rewrite/implementation-plan.md
  • greenfield/docs/architecture/greenfield-rewrite/progress.md
  • greenfield/docs/architecture/greenfield-rewrite/runtime-and-delivery.md
  • greenfield/migrations/20260804022252_dashboard-foundation/migration.sql
  • greenfield/migrations/20260804022252_dashboard-foundation/snapshot.json
  • greenfield/scripts/audits/openclaw/fixtures/2026.7.2-beta.7/manifest.json
  • greenfield/scripts/audits/openclaw/fixtures/2026.7.2-beta.7/operations.json
  • greenfield/scripts/audits/openclaw/reviewedFixtures.ts
  • greenfield/scripts/audits/openclaw/sourceAudit.ts
  • greenfield/scripts/audits/openclaw/sourceAuditSchemas.ts
  • greenfield/scripts/documentation/artifacts.test.ts
  • greenfield/scripts/documentation/jsonSchema.test.ts
  • greenfield/scripts/documentation/jsonSchema.ts
  • greenfield/scripts/sourceBoundaries/sourceTopologyPolicy.ts
  • greenfield/src/app/dashboardServer.test.ts
  • greenfield/src/app/dashboardServer.ts
  • greenfield/src/app/developmentWorker.ts
  • greenfield/src/app/server.ts
  • greenfield/src/app/trpcHttpHandler.ts
  • greenfield/src/app/trpcRequestPolicy.test.ts
  • greenfield/src/app/worker.test.ts
  • greenfield/src/app/worker.ts
  • greenfield/src/browser/api/trpcClient.ts
  • greenfield/src/browser/overview/OverviewRoute.test.tsx
  • greenfield/src/browser/overview/OverviewRoute.tsx
  • greenfield/src/browser/overview/OverviewServiceActionsCard.tsx
  • greenfield/src/browser/overview/OverviewServiceActionsSection.test.tsx
  • greenfield/src/browser/overview/OverviewServiceActionsSection.tsx
  • greenfield/src/browser/overview/serviceActionsOperations.test.ts
  • greenfield/src/browser/overview/serviceActionsOperations.ts
  • greenfield/src/contracts/contractRegistry.ts
  • greenfield/src/contracts/jobModel.ts
  • greenfield/src/contracts/security.test.ts
  • greenfield/src/contracts/security.ts
  • greenfield/src/contracts/serviceActions.test.ts
  • greenfield/src/contracts/serviceActions.ts
  • greenfield/src/server/database/migrations/jobsSchema.test.ts
  • greenfield/src/server/database/migrations/migrationGraph.test.ts
  • greenfield/src/server/database/schema/automationPrincipalCapabilities.ts
  • greenfield/src/server/database/schema/jobChecks.ts
  • greenfield/src/server/database/schema/jobRuns.ts
  • greenfield/src/server/database/schema/workerInstances.ts
  • greenfield/src/server/database/validation/jobRunEvents.ts
  • greenfield/src/server/database/validation/jobRuns.ts
  • greenfield/src/server/database/validation/rowSchemas.test.ts
  • greenfield/src/server/database/validation/workerInstances.ts
  • greenfield/src/server/domains/cache/repository.test.ts
  • greenfield/src/server/domains/jobs/actionExecutors.test.ts
  • greenfield/src/server/domains/jobs/actionExecutors.ts
  • greenfield/src/server/domains/jobs/actionRegistry.test.ts
  • greenfield/src/server/domains/jobs/actionRegistry.ts
  • greenfield/src/server/domains/jobs/coordinator.test.ts
  • greenfield/src/server/domains/jobs/coordinator.ts
  • greenfield/src/server/domains/jobs/repository.test.ts
  • greenfield/src/server/domains/jobs/repository.ts
  • greenfield/src/server/domains/jobs/service.test.ts
  • greenfield/src/server/domains/jobs/service.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.test.ts
  • greenfield/src/server/domains/jobs/serviceActionQueue.ts
  • greenfield/src/server/domains/jobs/workerRuntime.test.ts
  • greenfield/src/server/domains/jobs/workerRuntime.ts
  • greenfield/src/server/domains/serviceActions/procedures.test.ts
  • greenfield/src/server/domains/serviceActions/routes.ts
  • greenfield/src/server/domains/serviceActions/service.test.ts
  • greenfield/src/server/domains/serviceActions/service.ts
  • greenfield/src/server/domains/serviceActions/statusReader.test.ts
  • greenfield/src/server/domains/serviceActions/statusReader.ts
  • greenfield/src/server/platform/gateway/persistentGatewayOpenClawServiceActionsProvider.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayOpenClawServiceActionsProvider.ts
  • greenfield/src/server/platform/gateway/persistentGatewayProtocol.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayProtocol.ts
  • greenfield/src/server/platform/gateway/persistentGatewayTransport.test.ts
  • greenfield/src/server/platform/gateway/persistentGatewayTransport.ts
  • greenfield/src/server/platform/observability/structuredLogger.test.ts
  • greenfield/src/server/platform/observability/structuredLogger.ts
  • greenfield/src/server/test/support/requestContext.ts
  • greenfield/src/server/trpc/appRouter.ts
  • greenfield/src/server/trpc/context.test.ts
  • greenfield/src/server/trpc/context.ts
  • greenfield/src/server/trpc/procedureErrorPolicy.ts
  • greenfield/src/shared/databaseMigrationManifest.ts
  • greenfield/src/shared/openClawServiceActions.ts
  • greenfield/src/test/integration/openclaw/sourceAudit.test.ts
  • greenfield/src/test/parity/fixtures/greenfield-contracts.json
  • greenfield/src/test/parity/fixtures/legacy-endpoints.json
  • greenfield/src/test/parity/parityInventory.test.ts

Comment thread greenfield/scripts/audits/openclaw/sourceAudit.ts
Comment thread greenfield/src/browser/overview/OverviewServiceActionsCard.tsx Outdated
Comment thread greenfield/src/server/database/schema/workerInstances.ts
Comment thread greenfield/src/server/database/validation/workerInstances.ts
Comment thread greenfield/src/server/domains/jobs/actionExecutors.test.ts Outdated
Comment thread greenfield/src/server/domains/jobs/coordinator.ts
Comment thread greenfield/src/server/domains/serviceActions/statusReader.test.ts Outdated
Comment thread greenfield/src/server/platform/gateway/persistentGatewayProtocol.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: dacc3661b7

ℹ️ 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 greenfield/src/server/domains/serviceActions/service.ts
Comment thread greenfield/src/browser/overview/OverviewServiceActionsSection.tsx

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

ℹ️ 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 greenfield/src/server/platform/gateway/persistentGatewayProtocol.ts
Comment thread greenfield/src/browser/overview/OverviewServiceActionsCard.tsx 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: 76f61b1bf5

ℹ️ 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 greenfield/src/server/platform/gateway/persistentGatewayProtocol.ts
Comment thread greenfield/src/browser/overview/OverviewServiceActionsCard.tsx

@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: 41129fce48

ℹ️ 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 greenfield/src/server/domains/jobs/repository.ts
Comment thread greenfield/src/server/domains/serviceActions/statusReader.ts
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@rajohan

rajohan commented Aug 12, 2026

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 4373658c2d

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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: frontend Frontend UI, client state, routing, and browser behavior area: openclaw OpenClaw gateway/API integration and runtime behavior area: ops Operational actions, deploys, services, backups, and health status: needs-review Ready for human or agent review type: documentation Documentation, README, comments, and operational notes type: feature Adds user-visible functionality type: security Security, auth, secrets, or trust-boundary work type: tests Adds or updates automated tests/coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants