Skip to content

Observability and troubleshooting

The Workspace UI Project uses three existing Moltaro layers, each with a distinct purpose: build history owns exact authoring lifecycle diagnostics, the workspace DevLog owns bounded high-detail diagnostics for support, and the Administration Monitoring area owns the operational health signal. Workspace UI code is trusted workspace code compiled by Moltaro — the boundary is governance and review, so observability is about diagnosing builds and pages, not policing hostile code.

Build history is the primary diagnostic record. Every check and build is kept with its requested kind, status (Queued, Running, Succeeded, Failed, Cancelled), current stage, progress, duration, structured diagnostics, and a bounded error summary. Pipeline stages are explicit: resolving the offline Node toolchain, preparing an isolated working directory, validating source, generating the compilable Vue project, type-checking with vue-tsc, linting with ESLint, bundling, inspecting the output, and storing the immutable inactive artifact.

Each diagnostic carries a stable code, a severity (Info, Warning, or Error — only errors block the build), the emitting stage, and a file and range where the toolchain provides one. Read history through the Configuration API (View or Build permission):

GET /api/workspace/admin/ui-project/builds
GET /api/workspace/admin/ui-project/builds/{buildId}

A failed check or build never replaces the active artifact, so a red build is a diagnostic to read, not an outage.

Page code can emit best-effort breadcrumbs through the useDevLog() composable. It exposes only info, warning, and error, returns void, and never throws — logging can never break a page.

<script setup lang="ts">
import { useDevLog } from '@moltaro/workspace-ui'
const devLog = useDevLog()
devLog.info('orders-loaded', 'Orders page loaded', { rowCount: 42 })
devLog.error('orders-load-failed', 'Order query returned no rows')
</script>

Payloads are bounded and sanitized on the client: the event name is lowercase kebab-case up to 64 characters; the message is capped at 2048 characters; up to 16 primitive properties (string, number, boolean, null) are allowed with string values capped at 256 characters; URLs, secret-like tokens, and absolute file paths are redacted. Events queue in a capped buffer (oldest dropped first), flush in small batches, and dropped batches are not retried.

Accepted events appear as individual entries in the workspace DevLog with the workspace-ui-author source and the page key as category, alongside server-owned actor and artifact metadata. Author events are deliberately excluded from runtime-failure metrics and Monitoring status derivation — they are breadcrumbs for you, not health signals.

An incompatible or failing artifact does not execute. The core WebApp always completes its own startup; a broken custom artifact only affects pages under /apps/<pageKey>, which show a deliberate missing, incompatible, or load-failed state (plus permission-denied and render-error states) instead of a blank screen. The page host contains a Vue error boundary and automatically reports bounded, sanitized failure events — artifact load, registration, component resolution, render, and host-contract incompatibility — to the workspace DevLog.

Runtime health is surfaced through the Workspace UI signal in the Administration Monitoring area, not through a public endpoint. The signal shows toolchain readiness, the latest check or build, queue depth, the active artifact and its compatibility, runtime failures by fixed kind, the managed external-client outcome summary, recent diagnostic links, and the recommended next operator action. Monitoring is an observer: it links back to the authoring surfaces and never retries builds or activates artifacts itself.

Managed external client telemetry and its limits

Section titled “Managed external client telemetry and its limits”

Only the managed ExternalApiClient from the external API client emits telemetry, and only sanitized outcomes: an HTTP status family (2xx, 3xx, 4xx, 5xx, one combined network-or-browser family covering network errors and CORS or browser blocks, cancelled for aborted requests, and protocol for out-of-range statuses or parse failures) and duration. Destination URLs, origins, headers, request and response bodies, and credentials are never recorded, and page content never leaks into diagnostics. Direct browser fetch, WebSocket, and EventSource calls remain allowed but are not captured — Moltaro does not proxy or audit arbitrary browser traffic.

When the active artifact is broken, recovery is explicit and ordered:

  1. Stop the bleeding — deactivate the active artifact or roll back to a compatible previously published one (Publish permission): POST /api/workspace/admin/ui-project/artifacts/{artifactId}/deactivate, POST /api/workspace/admin/ui-project/artifacts/{artifactId}/rollback.
  2. Fix the source in UI Studio or via download/upload, then queue a new build with POST /api/workspace/admin/ui-project/builds (the request requires a RevisionId; Kind 0 is a Check, 1 is a Build).
  3. Reactivate with POST /api/workspace/admin/ui-project/artifacts/{artifactId}/activate; the response reports RefreshRequired, and the new artifact applies after a full WebApp refresh.

After a Moltaro update, check GET /api/workspace/admin/ui-project/compatibility — a rebuild may be required, and a breaking host-contract change can require source edits before the rebuild succeeds. The full lifecycle is covered in Build, publish, and upgrade; platform-level operations practices live under Operations.