Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -227,19 +227,70 @@ contract for automation merely because the caller is non-browser TypeScript.

### Compact automation heartbeat

`cache.getHeartbeat` is a versioned greenfield query under the existing `cache:read` automation
scope. It embeds the same at-most-128-row, payload-free cache status used by `cache.getStatus`, then
adds only the process-owned Gateway phase/freshness and identity-free summaries of the latest
validated current-session and global OpenClaw-cron projections. Session keys, display names, cron
`cache.getHeartbeat` schema v4 is a dedicated declassification query under the existing
`cache:read` automation scope. It embeds the same at-most-128-row, payload-free cache status used
by `cache.getStatus`, then adds process-owned Gateway freshness, bounded task and Dashboard-job
state, and identity-free OpenClaw-cron health. Session keys, display names, cron identifiers and
names, payloads, credentials, endpoints, and raw errors never cross this boundary.

The heartbeat does not issue a Gateway RPC. Before a bounded projection has been observed it says
`unavailable`; after a failed refresh or Gateway disconnect it retains the count as explicitly
`last-known-good`. Session truncation remains visible. Cron pending synchronization is `unknown`
when the cached global page cannot prove absence and `present` when any unsettled desired state is
known. This modern schema does not reproduce legacy schema-v3 task rows, Dashboard-job rows, or
payload-bearing cache envelopes, so the reviewed legacy endpoint remains planned until those
remaining consumers are deliberately migrated or removed.
Each heartbeat owns a fixed, fresh-only OpenClaw-cron inventory refresh instead of depending on
unrelated browser list traffic. The process single-flights refreshes, enforces an eight-second
aggregate deadline, admits one successful snapshot for 60 seconds, and applies a ten-second retry
gate after failure. Up to 1000 rows and 32 MiB of cumulative authenticated response-frame bytes are
admitted as one atomic candidate. The transport records exact encoded frame bytes before the
provider strips unknown fields; one already-received protocol-bounded page may cross the cumulative
limit, after which the walk stops without retry. Pages are fetched sequentially; each page must
share snapshot revision and total, advance exact offsets, and contain globally unique identifiers.
Each full row is immediately reduced to the small heartbeat-only projection, so payload and
schedule text do not accumulate across pages. Revision races receive one bounded retry. Only a
complete coherent candidate replaces state; failure retains the previous aggregate as
`last-known-good`, and truncation remains explicit.

The global cron summary includes inspected/enabled/disabled/running/failing counts plus
intentional versus unexpected disablement, separate synchronization conflict/pending counts, and
potentially stuck runs.
For each automation-linked task, the internal cron identifier is used only for process-local
correlation. The response reports `present` runtime/synchronization health, `missing` only when a
complete fresh inventory proves absence, or `unavailable` when freshness/truncation cannot support
that conclusion. Task candidates are read in a short SQLite transaction that closes before any
Gateway I/O, then the same immutable snapshot is allowlist-projected.

The task projection still returns at most 100 UUID-keyed open rows selected by the exact legacy
operational predicate, without task content, assignee identity, or cron identity. Dashboard jobs
enumerate every bounded code-owned definition and compact lifecycle state. Each local reader fails
independently to explicit `unavailable`, and cross-object validation prevents stale or truncated
cron state from asserting an unjustified missing task automation.

This schema v4 summary is not declared a replacement for legacy REST heartbeat schema v3. The
legacy endpoint also exposes payload-bearing cache diagnostics and identifiable task, Dashboard-job,
and per-cron rows. Its parity entry remains `planned` until those diagnostic capabilities and the
repo-external OpenClaw consumer migration are preserved without loss; production's live consumer
must not change before that cutover gate is satisfied.

### Authenticated health diagnostics

`system.healthDiagnostics` is the session-only replacement for the legacy detailed health route.
It has strict empty input and no automation capability. One request reads the live application
readiness controller, verified frontend/release composition facts, the sanitized process Gateway
state, the identity-free cached Gateway-session count, and one deferred-transaction SQLite health
aggregate. The release commit is used only inside the service to require a fresh online worker from
the exact serving release; release IDs, worker IDs/PIDs, session identities, Gateway endpoints,
payloads, and raw failures never serialize.

Application, database, frontend, verified release, and exact-release worker checks gate the
diagnostic aggregate. Gateway state, cached-session freshness, queue depth, and claim pause remain
non-gating operational data and do not alter the public readiness probe. Queue and dependency
failures become explicit `unavailable` components rather than healthy-looking zeroes or a failed
whole response. The queue reader counts only indexed active states and aggregates every fresh
worker in constant-size SQL output, independently of the bounded worker inventory used by the Jobs
UI. The authenticated header consumes this one snapshot instead of polling raw readiness, Gateway,
and Jobs separately. A failed background refresh retains the last validated snapshot but marks every
previously healthy component and the aggregate as stale; it can never leave an old green status
looking current.

This secure replacement closes the legacy health row's readiness/dependency capability. The old
route's wider application-observability counters remain tracked by the separate planned
`GET /api/metrics` row; `system.metrics` alone does not claim that broader parity.

### Browser-managed automation security

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,18 @@ restarts, or unbounded shell commands. Those operations become durable `job_runs
the worker.

The `cache:read` automation heartbeat is a separate sanitized projection, not a shortcut around
session or cron detail authorization. It reads only process-local validated summaries and bounded
payload-free cache status, performs no upstream refresh, and discloses no session/cron identity,
payload, credential, endpoint, or raw failure. Missing and last-known-good projection states remain
explicit so an empty count is never inferred from unavailable upstream state.
session, task, job, or cron detail authorization. It reads process-local validated Gateway
summaries plus bounded payload-free cache status and purpose-built SQLite task/Dashboard-job
projections, and requires neither `tasks:read` nor `jobs:read`. Its only upstream work is a
fixed read-only OpenClaw-cron inventory refresh with an aggregate deadline, atomic snapshot checks,
single-flight ownership, success TTL, and failure backoff.
Task content, assignee and cron identity, schedule metadata, payloads, results, events, actors,
workers, leases, credentials, endpoints, disable reasons, terminal messages, and raw failures do
not cross the boundary. Exact task count/truncation and the canonical row prefix share one short
read transaction that closes before Gateway I/O. Each local projection is structurally and semantically validated inside its own
safe reader boundary, so failure degrades only that projection to `unavailable`. Missing and
last-known-good Gateway states remain explicit so an empty count is never inferred from
unavailable upstream state.

Queue behavior is explicit:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ Gateway client, chat, production credential cutover, and complete rewrite remain
audio/text are strictly bounded, abortable, no-store, and never persisted or logged.
- expose a versioned compact automation heartbeat from process-owned state: bounded payload-free
cache status, sanitized Gateway phase/freshness, identity-free current-session count/truncation,
and global OpenClaw-cron count/pending-sync state. It must not perform an extra upstream refresh,
expose raw errors or identities, or claim legacy schema-v3 task/job-row parity.
and global OpenClaw-cron count/pending-sync state. It must own a bounded, fresh-only cron
inventory refresh rather than infer health from unrelated browser traffic, fetch pages
sequentially under explicit row/byte/deadline budgets, immediately retain only heartbeat fields,
never expose raw errors or identities, and not claim legacy schema-v3 task/job-row parity.

**Exit gate:** recorded Gateway fixtures and live smoke tests cover every chat parity item,
including restart during streaming.
Expand Down
Loading