diff --git a/.github/workflows/server-test.yaml b/.github/workflows/server-test.yaml index 11b809e8..6369b76b 100644 --- a/.github/workflows/server-test.yaml +++ b/.github/workflows/server-test.yaml @@ -36,6 +36,16 @@ jobs: cache: true cache-dependency-path: server/go.sum + # categorygen's checks (unclassified route, category that isn't control or + # platform, classified route with no handler) only run when the generator + # does, and its only other caller is `make oapi-generate`, which needs the + # npm down-converter. Running it here enforces them on every change. + - name: Check generated event categories are current + run: | + go generate ./lib/events/... + git diff --exit-code -- lib/events/category_gen.go + working-directory: server + - name: Run server unit tests run: make test-unit working-directory: server diff --git a/server/cmd/api/api/middleware.go b/server/cmd/api/api/middleware.go index a558199a..fe8ec194 100644 --- a/server/cmd/api/api/middleware.go +++ b/server/cmd/api/api/middleware.go @@ -19,6 +19,18 @@ type telemetryCtxKey struct{} type telemetryRequestCtx struct { operationID string + code string +} + +// RecordTelemetryCode attaches code submitted with the request to its api_call +// event, capped like every other captured string. It is a no-op when telemetry +// is off or the request is not one the middleware tracks. +func RecordTelemetryCode(ctx context.Context, code string) { + tc, ok := ctx.Value(telemetryCtxKey{}).(*telemetryRequestCtx) + if !ok { + return + } + tc.code = events.TruncateCaptured(code, events.CapturedFieldCap) } // Process-wide toggle for the api_call middleware. Flipped by @@ -35,9 +47,12 @@ func DisableTelemetryMiddleware() { telemetryMiddlewareEnabled.Store(false) } // TelemetryMiddlewareEnabled reports the current state. func TelemetryMiddlewareEnabled() bool { return telemetryMiddlewareEnabled.Load() } -// TelemetryHTTPMiddleware emits a BrowserApiCallEvent per documented operation, -// capturing the final status and wall-clock duration. publish is wired to -// TelemetrySession.Publish; the middleware ignores the returns. +// TelemetryHTTPMiddleware emits one event per documented operation, capturing +// the final status and wall-clock duration. Operations that drive the browser +// emit api_call under control; operations that manage the VM emit +// platform_api_call under platform, per the operation's x-telemetry-category in +// openapi.yaml. publish is wired to TelemetrySession.Publish; the middleware +// ignores the returns. func TelemetryHTTPMiddleware(publish func(events.Event) (events.Envelope, bool)) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -55,16 +70,12 @@ func TelemetryHTTPMiddleware(publish func(events.Event) (events.Envelope, bool)) if tc.operationID == "" { return } - data, _ := json.Marshal(oapi.BrowserApiCallEventData{ - RequestId: chiMiddleware.GetReqID(ctx), - OperationId: tc.operationID, - Status: ww.Status(), - DurationMs: float32(time.Since(start).Microseconds()) / 1000.0, - }) + eventType, category := apiCallEvent(tc.operationID) + data := apiCallEventData(category, tc, chiMiddleware.GetReqID(ctx), ww.Status(), time.Since(start)) publish(events.Event{ Ts: time.Now().UnixMicro(), - Type: "api_call", - Category: events.Control, + Type: eventType, + Category: category, Source: oapi.BrowserEventSource{Kind: oapi.KernelApi}, Data: data, }) @@ -72,6 +83,44 @@ func TelemetryHTTPMiddleware(publish func(events.Event) (events.Envelope, bool)) } } +// apiCallEventData marshals the payload for the resolved event type. The two +// types have separate schemas and only api_call declares code, so a platform +// call marshals the metadata-only type rather than a control payload that +// happens to have the field unset. +func apiCallEventData(category oapi.TelemetryEventCategory, tc *telemetryRequestCtx, requestID string, status int, duration time.Duration) []byte { + durationMs := float32(duration.Microseconds()) / 1000.0 + if category != events.Control { + data, _ := json.Marshal(oapi.BrowserPlatformApiCallEventData{ + RequestId: requestID, + OperationId: tc.operationID, + Status: status, + DurationMs: durationMs, + }) + return data + } + eventData := oapi.BrowserApiCallEventData{ + RequestId: requestID, + OperationId: tc.operationID, + Status: status, + DurationMs: durationMs, + } + if tc.code != "" { + eventData.Code = &tc.code + } + data, _ := json.Marshal(eventData) + return data +} + +// apiCallEvent resolves the event type and category for an operation. An +// operation missing from the generated map falls back to platform so an +// unclassified route cannot dilute the control stream. +func apiCallEvent(operationID string) (string, oapi.TelemetryEventCategory) { + if cat, ok := events.CategoryForOperation(operationID); ok && cat == events.Control { + return "api_call", events.Control + } + return "platform_api_call", events.Platform +} + // TelemetryStrictMiddleware records the matched OpenAPI operationId onto the // per-request scratch so TelemetryHTTPMiddleware can include it in the event. func TelemetryStrictMiddleware() oapi.StrictMiddlewareFunc { diff --git a/server/cmd/api/api/middleware_test.go b/server/cmd/api/api/middleware_test.go index 972967f4..e1d568e1 100644 --- a/server/cmd/api/api/middleware_test.go +++ b/server/cmd/api/api/middleware_test.go @@ -5,8 +5,10 @@ import ( "encoding/json" "net/http" "net/http/httptest" + "strings" "sync" "testing" + "unicode/utf8" chiMiddleware "github.com/go-chi/chi/v5/middleware" "github.com/stretchr/testify/assert" @@ -37,21 +39,23 @@ func (rp *recordingPublisher) snapshot() []events.Event { return out } -// Mirrors the oapi-codegen strict dispatcher: middleware chain -> inner -// handler -> response write. -func fakeStrictHandler(operationID string, status int, mws []oapi.StrictMiddlewareFunc) http.Handler { +// Mirrors the oapi-codegen strict dispatcher, running body inside the handler so +// a test can act on the request context the way a real handler does. +func fakeStrictHandlerFunc(operationID string, status int, body func(ctx context.Context)) http.Handler { inner := oapi.StrictHandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request, request any) (any, error) { + body(ctx) return nil, nil }) - for _, mw := range mws { - inner = mw(inner, operationID) - } + inner = TelemetryStrictMiddleware()(inner, operationID) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, _ = inner(r.Context(), w, r, nil) w.WriteHeader(status) }) } +// noBody is the handler body for tests that only exercise the middleware. +func noBody(context.Context) {} + // Flips the package-level toggle on for the test, restoring prior state // via t.Cleanup. func withTelemetryMiddlewareEnabled(t *testing.T) { @@ -70,9 +74,9 @@ func withTelemetryMiddlewareEnabled(t *testing.T) { func TestTelemetryMiddleware_EmitsApiCallEventOnDocumentedRoute(t *testing.T) { withTelemetryMiddlewareEnabled(t) rp := &recordingPublisher{} - chain := chiHandler(t, rp.publish, "ProcessExec", http.StatusOK) + chain := chiHandler(t, rp.publish, "ClickMouse", http.StatusOK, noBody) - req := httptest.NewRequest(http.MethodPost, "/process/exec", nil) + req := httptest.NewRequest(http.MethodPost, "/computer/click_mouse", nil) rec := httptest.NewRecorder() chain.ServeHTTP(rec, req) @@ -88,18 +92,105 @@ func TestTelemetryMiddleware_EmitsApiCallEventOnDocumentedRoute(t *testing.T) { OperationID string `json:"operation_id"` Status int `json:"status"` DurationMs float64 `json:"duration_ms"` + Code *string `json:"code"` } require.NoError(t, json.Unmarshal(ev.Data, &data)) assert.NotEmpty(t, data.RequestID, "request_id should be set by chi RequestID middleware") - assert.Equal(t, "ProcessExec", data.OperationID) + assert.Equal(t, "ClickMouse", data.OperationID) assert.Equal(t, http.StatusOK, data.Status) assert.GreaterOrEqual(t, data.DurationMs, 0.0) + assert.Nil(t, data.Code, "code is only recorded by handlers that submit code") +} + +func TestTelemetryMiddleware_EmitsPlatformApiCallForVMOperations(t *testing.T) { + withTelemetryMiddlewareEnabled(t) + rp := &recordingPublisher{} + // Records code from a platform handler, which no handler does today, to pin + // that the payload type and not the call sites is what keeps it out. + chain := chiHandler(t, rp.publish, "ProcessExec", http.StatusOK, func(ctx context.Context) { + RecordTelemetryCode(ctx, "await page.goto('https://example.com')") + }) + + req := httptest.NewRequest(http.MethodPost, "/process/exec", nil) + chain.ServeHTTP(httptest.NewRecorder(), req) + + captured := rp.snapshot() + require.Len(t, captured, 1) + assert.Equal(t, "platform_api_call", captured[0].Type) + assert.Equal(t, events.Platform, captured[0].Category) + // BrowserPlatformApiCallEventData declares no code field, so the key must be + // absent for the payload to match the published schema. + assert.NotContains(t, string(captured[0].Data), `"code"`) +} + +// An operation the generated map does not know about must not land in control, +// which is the stream callers read to see what the agent did. +func TestTelemetryMiddleware_UnknownOperationIsPlatform(t *testing.T) { + withTelemetryMiddlewareEnabled(t) + rp := &recordingPublisher{} + chain := chiHandler(t, rp.publish, "SomeRouteAddedLater", http.StatusOK, noBody) + + chain.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(http.MethodPost, "/whatever", nil)) + + captured := rp.snapshot() + require.Len(t, captured, 1) + assert.Equal(t, events.Platform, captured[0].Category) +} + +func TestTelemetryMiddleware_RecordsSubmittedCode(t *testing.T) { + withTelemetryMiddlewareEnabled(t) + rp := &recordingPublisher{} + code := "await page.goto('https://example.com')" + chain := chiHandler(t, rp.publish, "ExecutePlaywrightCode", http.StatusOK, func(ctx context.Context) { + RecordTelemetryCode(ctx, code) + }) + + chain.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(http.MethodPost, "/playwright/execute", nil)) + + captured := rp.snapshot() + require.Len(t, captured, 1) + assert.Equal(t, events.Control, captured[0].Category) + assert.False(t, captured[0].Truncated) + var data struct { + Code *string `json:"code"` + } + require.NoError(t, json.Unmarshal(captured[0].Data, &data)) + require.NotNil(t, data.Code) + assert.Equal(t, code, *data.Code) +} + +func TestTelemetryMiddleware_ClipsOversizedCode(t *testing.T) { + withTelemetryMiddlewareEnabled(t) + rp := &recordingPublisher{} + // Ends on a multi-byte rune straddling the cap so the clip has to back off. + oversized := strings.Repeat("x", events.CapturedFieldCap-1) + strings.Repeat("é", 10) + chain := chiHandler(t, rp.publish, "ExecutePlaywrightCode", http.StatusOK, func(ctx context.Context) { + RecordTelemetryCode(ctx, oversized) + }) + + chain.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(http.MethodPost, "/playwright/execute", nil)) + + captured := rp.snapshot() + require.Len(t, captured, 1) + var data struct { + Code string `json:"code"` + } + require.NoError(t, json.Unmarshal(captured[0].Data, &data)) + assert.True(t, strings.HasSuffix(data.Code, events.TruncatedSuffix), "clipped code is not marked: %q", data.Code[max(0, len(data.Code)-40):]) + assert.LessOrEqual(t, len(data.Code), events.CapturedFieldCap) + assert.True(t, utf8.ValidString(data.Code)) +} + +// RecordTelemetryCode is called from handlers that also serve requests the +// middleware is not tracking, so it must tolerate a bare context. +func TestRecordTelemetryCode_NoopWithoutRequestScratch(t *testing.T) { + RecordTelemetryCode(context.Background(), "await page.goto('https://example.com')") } func TestTelemetryMiddleware_CapturesNonOKStatus(t *testing.T) { withTelemetryMiddlewareEnabled(t) rp := &recordingPublisher{} - chain := chiHandler(t, rp.publish, "ProcessExec", http.StatusInternalServerError) + chain := chiHandler(t, rp.publish, "ProcessExec", http.StatusInternalServerError, noBody) req := httptest.NewRequest(http.MethodPost, "/process/exec", nil) rec := httptest.NewRecorder() @@ -131,7 +222,7 @@ func TestTelemetryMiddleware_SkipsUndocumentedRoutes(t *testing.T) { func TestTelemetryMiddleware_ShortCircuitsWhenDisabled(t *testing.T) { DisableTelemetryMiddleware() rp := &recordingPublisher{} - chain := chiHandler(t, rp.publish, "ProcessExec", http.StatusOK) + chain := chiHandler(t, rp.publish, "ProcessExec", http.StatusOK, noBody) req := httptest.NewRequest(http.MethodPost, "/process/exec", nil) rec := httptest.NewRecorder() @@ -142,9 +233,9 @@ func TestTelemetryMiddleware_ShortCircuitsWhenDisabled(t *testing.T) { // Builds the same middleware stack as main.go: RequestID -> HTTP middleware -> // strict dispatch -> inner handler. -func chiHandler(t *testing.T, publish func(events.Event) (events.Envelope, bool), operationID string, status int) http.Handler { +func chiHandler(t *testing.T, publish func(events.Event) (events.Envelope, bool), operationID string, status int, body func(ctx context.Context)) http.Handler { t.Helper() - inner := fakeStrictHandler(operationID, status, []oapi.StrictMiddlewareFunc{TelemetryStrictMiddleware()}) + inner := fakeStrictHandlerFunc(operationID, status, body) telemetry := TelemetryHTTPMiddleware(publish)(inner) return chiMiddleware.RequestID(telemetry) } diff --git a/server/cmd/api/api/playwright.go b/server/cmd/api/api/playwright.go index de7368ab..395a45ed 100644 --- a/server/cmd/api/api/playwright.go +++ b/server/cmd/api/api/playwright.go @@ -144,6 +144,8 @@ func (s *ApiService) ExecutePlaywrightCode(ctx context.Context, request oapi.Exe }, nil } + RecordTelemetryCode(ctx, request.Body.Code) + timeout := 60 * time.Second if request.Body.TimeoutSec != nil && *request.Body.TimeoutSec > 0 { timeout = time.Duration(*request.Body.TimeoutSec) * time.Second diff --git a/server/cmd/api/api/telemetry.go b/server/cmd/api/api/telemetry.go index 52dc6b1f..a45ca3ba 100644 --- a/server/cmd/api/api/telemetry.go +++ b/server/cmd/api/api/telemetry.go @@ -117,13 +117,14 @@ func (s *ApiService) PatchTelemetry(ctx context.Context, req oapi.PatchTelemetry } // reconcileTelemetryState reconciles the CDP collector and the api_call -// (control) middleware to the desired category set. The collector runs iff a -// CDP category is captured; the middleware emits iff the control category is. -// Callers commit the session config first so the filter is live before the -// collector emits; this returns an error only when the collector fails to -// start, leaving the caller to roll back. +// middleware to the desired category set. The collector runs iff a CDP category +// is captured; the middleware emits iff control or platform is, since it is the +// sole producer of both api_call and platform_api_call. Callers commit the +// session config first so the filter is live before the collector emits; this +// returns an error only when the collector fails to start, leaving the caller to +// roll back. func (s *ApiService) reconcileTelemetryState(cats []oapi.TelemetryEventCategory) error { - if containsCategory(cats, events.Control) { + if containsCategory(cats, events.Control) || containsCategory(cats, events.Platform) { EnableTelemetryMiddleware() } else { DisableTelemetryMiddleware() @@ -221,6 +222,7 @@ func categoryFields(b *oapi.BrowserTelemetryCategoriesConfig) []categoryField { {events.Page, b.Page}, {events.Interaction, b.Interaction}, {events.Control, b.Control}, + {events.Platform, b.Platform}, {events.Connection, b.Connection}, {events.System, b.System}, {events.Screenshot, b.Screenshot}, @@ -332,6 +334,7 @@ func disabledConfig() oapi.BrowserTelemetryConfig { Page: off(), Interaction: off(), Control: off(), + Platform: off(), Connection: off(), System: off(), Screenshot: off(), @@ -363,6 +366,7 @@ func telemetryConfigToOAPI(cfg telemetry.TelemetryConfig) oapi.BrowserTelemetryC Page: enabled(events.Page), Interaction: enabled(events.Interaction), Control: enabled(events.Control), + Platform: enabled(events.Platform), Connection: enabled(events.Connection), System: enabled(events.System), Screenshot: enabled(events.Screenshot), diff --git a/server/cmd/api/api/telemetry_test.go b/server/cmd/api/api/telemetry_test.go index 5b7261cf..ec69d07b 100644 --- a/server/cmd/api/api/telemetry_test.go +++ b/server/cmd/api/api/telemetry_test.go @@ -29,6 +29,7 @@ func allCategoriesDisabled() *oapi.BrowserTelemetryCategoriesConfig { Page: off(), Interaction: off(), Control: off(), + Platform: off(), Connection: off(), System: off(), Screenshot: off(), @@ -230,6 +231,47 @@ func TestTelemetryHandlersDriveMiddlewareToggle(t *testing.T) { assert.False(t, TelemetryMiddlewareEnabled(), "all-disabled PUT should leave middleware off") } +// The middleware is the sole producer of platform_api_call as well as api_call, +// so a reader who migrates from control to platform must still get events. +func TestTelemetryHandlersEnableMiddlewareForPlatformOnly(t *testing.T) { + ctx := context.Background() + t.Cleanup(DisableTelemetryMiddleware) + + svc := newTestService(t, newMockRecordManager()) + + DisableTelemetryMiddleware() + tr, f := true, false + _, err := svc.PutTelemetry(ctx, oapi.PutTelemetryRequestObject{ + Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{ + Platform: &oapi.BrowserTelemetryCategoryConfig{Enabled: &tr}, + }, + }, + }) + require.NoError(t, err) + assert.True(t, TelemetryMiddlewareEnabled(), "PUT with platform=true should enable middleware") + + _, err = svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{ + Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{ + Control: &oapi.BrowserTelemetryCategoryConfig{Enabled: &f}, + }, + }, + }) + require.NoError(t, err) + assert.True(t, TelemetryMiddlewareEnabled(), "dropping control should leave the middleware on for platform") + + _, err = svc.PatchTelemetry(ctx, oapi.PatchTelemetryRequestObject{ + Body: &oapi.BrowserTelemetryConfig{ + Browser: &oapi.BrowserTelemetryCategoriesConfig{ + Platform: &oapi.BrowserTelemetryCategoryConfig{Enabled: &f}, + }, + }, + }) + require.NoError(t, err) + assert.False(t, TelemetryMiddlewareEnabled(), "dropping platform too should disable middleware") +} + func TestGetTelemetry(t *testing.T) { ctx := context.Background() diff --git a/server/e2e/e2e_otlp_storage_test.go b/server/e2e/e2e_otlp_storage_test.go index afd703cb..8610e07d 100644 --- a/server/e2e/e2e_otlp_storage_test.go +++ b/server/e2e/e2e_otlp_storage_test.go @@ -99,7 +99,8 @@ func (c *otlpMockCollector) snapshot() (auths, instanceName, eventNames []string } // enableControlExport turns on the control category (so api_call events flow) -// and OTLP export, then makes a few API calls to generate exportable events. +// and OTLP export, then makes a few browser-control calls to generate +// exportable events. func enableControlExport(t *testing.T, ctx context.Context, client *instanceoapi.ClientWithResponses) { t.Helper() tr := true @@ -113,9 +114,9 @@ func enableControlExport(t *testing.T, ctx context.Context, client *instanceoapi }) require.NoError(t, err) require.Equal(t, http.StatusCreated, resp.StatusCode(), "put telemetry: %s", string(resp.Body)) - // Each API call emits an api_call (control) event, which OTLP exports. + // Browser-control calls emit api_call (control) events, which OTLP exports. for i := 0; i < 3; i++ { - _, _ = client.GetTelemetryWithResponse(ctx) + _, _ = client.TakeScreenshotWithResponse(ctx, instanceoapi.TakeScreenshotJSONRequestBody{}) time.Sleep(50 * time.Millisecond) } } diff --git a/server/lib/cdpmonitor/handlers.go b/server/lib/cdpmonitor/handlers.go index f551cc03..c3eb684d 100644 --- a/server/lib/cdpmonitor/handlers.go +++ b/server/lib/cdpmonitor/handlers.go @@ -580,7 +580,7 @@ func (m *Monitor) fetchResponseBody(ctx context.Context, requestID, sessionID st } body = string(decoded) } - return truncateBody(body, bodyCapFor(state.mimeType)) + return events.TruncateCaptured(body, bodyCapFor(state.mimeType)) } func (m *Monitor) handleLoadingFailed(p cdpNetworkLoadingFailedParams, sessionID string) { diff --git a/server/lib/cdpmonitor/util.go b/server/lib/cdpmonitor/util.go index df03e44a..05117cb6 100644 --- a/server/lib/cdpmonitor/util.go +++ b/server/lib/cdpmonitor/util.go @@ -3,8 +3,8 @@ package cdpmonitor import ( "encoding/json" "strings" - "unicode/utf8" + "github.com/kernel/kernel-images/server/lib/events" oapi "github.com/kernel/kernel-images/server/lib/oapi" ) @@ -97,7 +97,7 @@ var structuredPrefixes = []string{ // Vendor types with +json, +xml, or +csv suffixes are also treated as structured, // matching the allow-list in isCapturedMIME. func bodyCapFor(mime string) int { - const fullCap = 8 * 1024 + const fullCap = events.CapturedFieldCap const contextCap = 4 * 1024 for _, p := range structuredPrefixes { if strings.HasPrefix(mime, p) { @@ -112,32 +112,3 @@ func bodyCapFor(mime string) int { } return contextCap } - -const truncatedSuffix = "...[truncated]" - -// truncateBody caps body at the given limit on a valid UTF-8 boundary. -// The result never splits a multi-byte rune. A truncation suffix is appended -// when the body is cut so callers can distinguish truncated from full content. -func truncateBody(body string, maxBody int) string { - if len(body) <= maxBody { - return body - } - if maxBody <= 0 { - return "" - } - // Reserve room for the truncation suffix within the limit. - cutAt := maxBody - len(truncatedSuffix) - if cutAt <= 0 { - return truncatedSuffix[:maxBody] - } - // Walk forward through complete runes, stopping before we exceed cutAt. - end := 0 - for end < cutAt { - _, size := utf8.DecodeRuneInString(body[end:]) - if end+size > cutAt { - break - } - end += size - } - return body[:end] + truncatedSuffix -} diff --git a/server/lib/events/capture.go b/server/lib/events/capture.go new file mode 100644 index 00000000..191d5144 --- /dev/null +++ b/server/lib/events/capture.go @@ -0,0 +1,40 @@ +package events + +import "unicode/utf8" + +// TruncatedSuffix marks a captured string that was cut at its cap, so a +// consumer can tell a clipped value from a complete one. +const TruncatedSuffix = "...[truncated]" + +// CapturedFieldCap is the ceiling for a single captured string on an event: +// response bodies of structured types, and the source submitted to Playwright +// execution. It sits two orders of magnitude below maxS2RecordBytes so no one +// field can push an envelope past the record limit, which would null the whole +// payload rather than clip the field. +const CapturedFieldCap = 8 * 1024 + +// TruncateCaptured caps s at maxBytes on a rune boundary, so the result never +// splits a multi-byte character, and appends TruncatedSuffix when it cuts. +func TruncateCaptured(s string, maxBytes int) string { + if len(s) <= maxBytes { + return s + } + if maxBytes <= 0 { + return "" + } + // Reserve room for the suffix within the cap. + cutAt := maxBytes - len(TruncatedSuffix) + if cutAt <= 0 { + return TruncatedSuffix[:maxBytes] + } + // Walk forward through complete runes, stopping before we exceed cutAt. + end := 0 + for end < cutAt { + _, size := utf8.DecodeRuneInString(s[end:]) + if end+size > cutAt { + break + } + end += size + } + return s[:end] + TruncatedSuffix +} diff --git a/server/lib/events/capture_test.go b/server/lib/events/capture_test.go new file mode 100644 index 00000000..c25febfc --- /dev/null +++ b/server/lib/events/capture_test.go @@ -0,0 +1,40 @@ +package events + +import ( + "strings" + "testing" + "unicode/utf8" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTruncateCaptured(t *testing.T) { + t.Run("a value within the cap is untouched", func(t *testing.T) { + assert.Equal(t, "page.click('#login')", TruncateCaptured("page.click('#login')", CapturedFieldCap)) + }) + + t.Run("a value over the cap is marked", func(t *testing.T) { + got := TruncateCaptured(strings.Repeat("a", CapturedFieldCap+1), CapturedFieldCap) + require.True(t, strings.HasSuffix(got, TruncatedSuffix)) + assert.LessOrEqual(t, len(got), CapturedFieldCap) + }) + + t.Run("the cut never splits a character", func(t *testing.T) { + // Every rune is 3 bytes, so a byte-wise cut lands inside one. + got := TruncateCaptured(strings.Repeat("あ", 40), 41) + assert.True(t, utf8.ValidString(got), "result is not valid UTF-8: %q", got) + assert.LessOrEqual(t, len(got), 41) + }) + + t.Run("a cap too small for the marker yields only the marker", func(t *testing.T) { + assert.Equal(t, TruncatedSuffix[:4], TruncateCaptured("abcdefghij", 4)) + assert.Equal(t, "", TruncateCaptured("abcdefghij", 0)) + }) + + // The cap exists so one field cannot push an envelope past the record limit, + // which would null the whole payload instead of clipping the field. + t.Run("the field cap leaves room under the record limit", func(t *testing.T) { + assert.Less(t, CapturedFieldCap, maxS2RecordBytes) + }) +} diff --git a/server/lib/events/category_gen.go b/server/lib/events/category_gen.go index b02132f9..e7fa54b5 100644 --- a/server/lib/events/category_gen.go +++ b/server/lib/events/category_gen.go @@ -34,6 +34,7 @@ var categoryByType = map[string]oapi.TelemetryEventCategory{ "page_navigation": oapi.TelemetryEventCategory("page"), "page_navigation_settled": oapi.TelemetryEventCategory("page"), "page_tab_opened": oapi.TelemetryEventCategory("page"), + "platform_api_call": oapi.TelemetryEventCategory("platform"), "service_crashed": oapi.TelemetryEventCategory("system"), "system_oom_kill": oapi.TelemetryEventCategory("system"), } @@ -44,3 +45,70 @@ func CategoryForType(eventType string) (oapi.TelemetryEventCategory, bool) { c, ok := categoryByType[eventType] return c, ok } + +var categoryByOperationID = map[string]oapi.TelemetryEventCategory{ + "BatchComputerAction": oapi.TelemetryEventCategory("control"), + "ChromiumConfigure": oapi.TelemetryEventCategory("platform"), + "ClickMouse": oapi.TelemetryEventCategory("control"), + "CreateDirectory": oapi.TelemetryEventCategory("platform"), + "DeleteDirectory": oapi.TelemetryEventCategory("platform"), + "DeleteFile": oapi.TelemetryEventCategory("platform"), + "DeleteRecording": oapi.TelemetryEventCategory("platform"), + "DisableScaleToZero": oapi.TelemetryEventCategory("platform"), + "DownloadDirZip": oapi.TelemetryEventCategory("platform"), + "DownloadDirZstd": oapi.TelemetryEventCategory("platform"), + "DownloadRecording": oapi.TelemetryEventCategory("platform"), + "DragMouse": oapi.TelemetryEventCategory("control"), + "EnableScaleToZero": oapi.TelemetryEventCategory("platform"), + "ExecutePlaywrightCode": oapi.TelemetryEventCategory("control"), + "FileInfo": oapi.TelemetryEventCategory("platform"), + "GetMousePosition": oapi.TelemetryEventCategory("control"), + "GetTelemetry": oapi.TelemetryEventCategory("platform"), + "ListFiles": oapi.TelemetryEventCategory("platform"), + "ListRecorders": oapi.TelemetryEventCategory("platform"), + "LogsStream": oapi.TelemetryEventCategory("platform"), + "MarkRecording": oapi.TelemetryEventCategory("platform"), + "MoveMouse": oapi.TelemetryEventCategory("control"), + "MovePath": oapi.TelemetryEventCategory("platform"), + "PatchChromiumFlags": oapi.TelemetryEventCategory("platform"), + "PatchChromiumPolicies": oapi.TelemetryEventCategory("platform"), + "PatchDisplay": oapi.TelemetryEventCategory("platform"), + "PatchTelemetry": oapi.TelemetryEventCategory("platform"), + "PressKey": oapi.TelemetryEventCategory("control"), + "ProcessExec": oapi.TelemetryEventCategory("platform"), + "ProcessKill": oapi.TelemetryEventCategory("platform"), + "ProcessResize": oapi.TelemetryEventCategory("platform"), + "ProcessSpawn": oapi.TelemetryEventCategory("platform"), + "ProcessStatus": oapi.TelemetryEventCategory("platform"), + "ProcessStdin": oapi.TelemetryEventCategory("platform"), + "ProcessStdoutStream": oapi.TelemetryEventCategory("platform"), + "PublishTelemetryEvent": oapi.TelemetryEventCategory("platform"), + "PutTelemetry": oapi.TelemetryEventCategory("platform"), + "ReadClipboard": oapi.TelemetryEventCategory("control"), + "ReadFile": oapi.TelemetryEventCategory("platform"), + "Scroll": oapi.TelemetryEventCategory("control"), + "SetCursor": oapi.TelemetryEventCategory("control"), + "SetFilePermissions": oapi.TelemetryEventCategory("platform"), + "StartFsWatch": oapi.TelemetryEventCategory("platform"), + "StartRecording": oapi.TelemetryEventCategory("platform"), + "StopFsWatch": oapi.TelemetryEventCategory("platform"), + "StopRecording": oapi.TelemetryEventCategory("platform"), + "StreamFsEvents": oapi.TelemetryEventCategory("platform"), + "StreamTelemetryEvents": oapi.TelemetryEventCategory("platform"), + "TakeScreenshot": oapi.TelemetryEventCategory("control"), + "TypeText": oapi.TelemetryEventCategory("control"), + "UploadExtensionsAndRestart": oapi.TelemetryEventCategory("platform"), + "UploadFiles": oapi.TelemetryEventCategory("platform"), + "UploadZip": oapi.TelemetryEventCategory("platform"), + "UploadZstd": oapi.TelemetryEventCategory("platform"), + "WriteClipboard": oapi.TelemetryEventCategory("control"), + "WriteFile": oapi.TelemetryEventCategory("platform"), +} + +// CategoryForOperation returns the category an api_call event carries for +// the given operation, keyed by the generated handler name the event +// reports. ok is false for an unknown operation. +func CategoryForOperation(operationID string) (oapi.TelemetryEventCategory, bool) { + c, ok := categoryByOperationID[operationID] + return c, ok +} diff --git a/server/lib/events/category_test.go b/server/lib/events/category_test.go new file mode 100644 index 00000000..8745723f --- /dev/null +++ b/server/lib/events/category_test.go @@ -0,0 +1,47 @@ +package events + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + oapi "github.com/kernel/kernel-images/server/lib/oapi" +) + +// The api_call/platform_api_call split is only meaningful if the operation map +// and the event-type map agree on which category each type carries. +func TestCategoryMapsAgreeOnAPICallSplit(t *testing.T) { + cat, ok := CategoryForType("api_call") + require.True(t, ok) + assert.Equal(t, Control, cat) + + cat, ok = CategoryForType("platform_api_call") + require.True(t, ok) + assert.Equal(t, Platform, cat) +} + +func TestCategoryForOperation(t *testing.T) { + require.NotEmpty(t, categoryByOperationID, "generator produced no operations") + + // Sampled rather than exhaustive: the spec is the source of truth for the + // full mapping, and restating all of it here would just be a second copy. + control, ok := CategoryForOperation("ExecutePlaywrightCode") + require.True(t, ok) + assert.Equal(t, Control, control) + + platform, ok := CategoryForOperation("StartRecording") + require.True(t, ok) + assert.Equal(t, Platform, platform) + + _, ok = CategoryForOperation("NotAnOperation") + assert.False(t, ok) +} + +// Every operation must land in one of the two api_call categories: any other +// category would produce an event type nothing publishes. +func TestOperationCategoriesAreAPICallCategories(t *testing.T) { + for operationID, cat := range categoryByOperationID { + assert.Contains(t, []oapi.TelemetryEventCategory{Control, Platform}, cat, "operation %s", operationID) + } +} diff --git a/server/lib/events/event.go b/server/lib/events/event.go index ab4f4270..904e4126 100644 --- a/server/lib/events/event.go +++ b/server/lib/events/event.go @@ -1,6 +1,6 @@ package events -//go:generate go run github.com/kernel/kernel-images/server/scripts/categorygen -openapi ../../openapi.yaml -out category_gen.go +//go:generate go run github.com/kernel/kernel-images/server/scripts/categorygen -openapi ../../openapi.yaml -handlers ../oapi/oapi.go -out category_gen.go import ( "encoding/json" @@ -18,6 +18,7 @@ const ( Page = oapi.TelemetryEventCategory("page") Interaction = oapi.TelemetryEventCategory("interaction") Control = oapi.TelemetryEventCategory("control") + Platform = oapi.TelemetryEventCategory("platform") Connection = oapi.TelemetryEventCategory("connection") System = oapi.TelemetryEventCategory("system") Screenshot = oapi.TelemetryEventCategory("screenshot") @@ -34,6 +35,7 @@ var UserCategories = []oapi.TelemetryEventCategory{ Page, Interaction, Control, + Platform, Connection, System, Screenshot, @@ -44,6 +46,8 @@ var UserCategories = []oapi.TelemetryEventCategory{ // per-category settings: the lightweight operational signals. CDP categories // (console/network/page/interaction) and screenshot are excluded so the default // never starts the CDP collector or emits high-volume streams; they are opt-in. +// Platform is excluded too: those calls are mostly platform-induced bookkeeping +// (recording, profile save) that drowns out the agent's own actions. var DefaultCategories = []oapi.TelemetryEventCategory{ Control, Connection, diff --git a/server/lib/oapi/oapi.go b/server/lib/oapi/oapi.go index 038414a3..2104712e 100644 --- a/server/lib/oapi/oapi.go +++ b/server/lib/oapi/oapi.go @@ -1028,6 +1028,36 @@ func (e BrowserPageTabOpenedEventType) Valid() bool { } } +// Defines values for BrowserPlatformApiCallEventCategory. +const ( + Platform BrowserPlatformApiCallEventCategory = "platform" +) + +// Valid indicates whether the value is a known member of the BrowserPlatformApiCallEventCategory enum. +func (e BrowserPlatformApiCallEventCategory) Valid() bool { + switch e { + case Platform: + return true + default: + return false + } +} + +// Defines values for BrowserPlatformApiCallEventType. +const ( + PlatformApiCall BrowserPlatformApiCallEventType = "platform_api_call" +) + +// Valid indicates whether the value is a known member of the BrowserPlatformApiCallEventType enum. +func (e BrowserPlatformApiCallEventType) Valid() bool { + switch e { + case PlatformApiCall: + return true + default: + return false + } +} + // Defines values for BrowserServiceCrashedEventCategory. const ( BrowserServiceCrashedEventCategorySystem BrowserServiceCrashedEventCategory = "system" @@ -1449,6 +1479,7 @@ const ( PublishEventRequestCategoryMonitor PublishEventRequestCategory = "monitor" PublishEventRequestCategoryNetwork PublishEventRequestCategory = "network" PublishEventRequestCategoryPage PublishEventRequestCategory = "page" + PublishEventRequestCategoryPlatform PublishEventRequestCategory = "platform" PublishEventRequestCategoryScreenshot PublishEventRequestCategory = "screenshot" PublishEventRequestCategorySystem PublishEventRequestCategory = "system" ) @@ -1472,6 +1503,8 @@ func (e PublishEventRequestCategory) Valid() bool { return true case PublishEventRequestCategoryPage: return true + case PublishEventRequestCategoryPlatform: + return true case PublishEventRequestCategoryScreenshot: return true case PublishEventRequestCategorySystem: @@ -1491,6 +1524,7 @@ const ( TelemetryEventCategoryMonitor TelemetryEventCategory = "monitor" TelemetryEventCategoryNetwork TelemetryEventCategory = "network" TelemetryEventCategoryPage TelemetryEventCategory = "page" + TelemetryEventCategoryPlatform TelemetryEventCategory = "platform" TelemetryEventCategoryScreenshot TelemetryEventCategory = "screenshot" TelemetryEventCategorySystem TelemetryEventCategory = "system" ) @@ -1514,6 +1548,8 @@ func (e TelemetryEventCategory) Valid() bool { return true case TelemetryEventCategoryPage: return true + case TelemetryEventCategoryPlatform: + return true case TelemetryEventCategoryScreenshot: return true case TelemetryEventCategorySystem: @@ -1586,7 +1622,7 @@ type BatchComputerActionRequest struct { Actions []ComputerAction `json:"actions"` } -// BrowserApiCallEvent An HTTP call handled by the kernel-images-api server. +// BrowserApiCallEvent A call that drives the browser, handled by the kernel-images-api server: computer-control actions, Playwright code execution, screenshots and clipboard access. Calls that manage the VM instead emit `platform_api_call`. type BrowserApiCallEvent struct { Category BrowserApiCallEventCategory `json:"category"` @@ -1612,10 +1648,13 @@ type BrowserApiCallEventType string // BrowserApiCallEventData Per-call payload for `api_call` events. type BrowserApiCallEventData struct { + // Code Source submitted to `executePlaywrightCode`, capped at 8192 bytes like every other captured string. A capped value is cut on a character boundary and ends in `...[truncated]`. Absent for every other operation. + Code *string `json:"code,omitempty"` + // DurationMs Wall-clock duration of the handler in milliseconds. DurationMs float32 `json:"duration_ms"` - // OperationId OpenAPI operationId of the matched route (e.g. `processExec`, `takeScreenshot`). + // OperationId Matched route's operation, named as the server names its handler (e.g. `TakeScreenshot`, `ExecutePlaywrightCode`). OperationId string `json:"operation_id"` // RequestId Per-request identifier from the kernel-images-api request middleware. @@ -2947,6 +2986,45 @@ type BrowserPageTabOpenedEventData struct { Url string `json:"url"` } +// BrowserPlatformApiCallEvent A call that manages the browser VM rather than driving the browser, handled by the kernel-images-api server: recording lifecycle, filesystem and process management, telemetry and browser configuration. These are mostly platform-induced (e.g. profile save, replay capture) rather than agent actions. +type BrowserPlatformApiCallEvent struct { + Category BrowserPlatformApiCallEventCategory `json:"category"` + + // Data Per-call payload for `platform_api_call` events. Metadata only: a platform call carries no submitted content, so there is no `code` field as there is on `api_call`. + Data *BrowserPlatformApiCallEventData `json:"data,omitempty"` + + // Source Provenance metadata identifying which producer emitted the event. + Source BrowserEventSource `json:"source"` + + // Truncated True if the data field was truncated due to size limits. + Truncated *bool `json:"truncated,omitempty"` + + // Ts Event timestamp in Unix microseconds. + Ts int64 `json:"ts"` + Type BrowserPlatformApiCallEventType `json:"type"` +} + +// BrowserPlatformApiCallEventCategory defines model for BrowserPlatformApiCallEvent.Category. +type BrowserPlatformApiCallEventCategory string + +// BrowserPlatformApiCallEventType defines model for BrowserPlatformApiCallEvent.Type. +type BrowserPlatformApiCallEventType string + +// BrowserPlatformApiCallEventData Per-call payload for `platform_api_call` events. Metadata only: a platform call carries no submitted content, so there is no `code` field as there is on `api_call`. +type BrowserPlatformApiCallEventData struct { + // DurationMs Wall-clock duration of the handler in milliseconds. + DurationMs float32 `json:"duration_ms"` + + // OperationId Matched route's operation, named as the server names its handler (e.g. `ProcessExec`, `StartRecording`). + OperationId string `json:"operation_id"` + + // RequestId Per-request identifier from the kernel-images-api request middleware. + RequestId string `json:"request_id"` + + // Status HTTP response status code. + Status int `json:"status"` +} + // BrowserServiceCrashedEvent A managed service exited unexpectedly. Intentional stops (e.g. operator-initiated shutdown) do not produce this event — only unexpected exits and terminal restart-give-up transitions do. type BrowserServiceCrashedEvent struct { Category BrowserServiceCrashedEventCategory `json:"category"` @@ -3069,7 +3147,7 @@ type BrowserTelemetryCategoriesConfig struct { // Console Console output (log, warn, error) and uncaught exceptions. Console *BrowserTelemetryCategoryConfig `json:"console,omitempty"` - // Control Agent-driven actions against the browser, such as inbound calls to the kernel-images-api server. + // Control Agent-driven actions against the browser — computer-control calls, Playwright code execution, screenshots and clipboard access. Control *BrowserTelemetryCategoryConfig `json:"control,omitempty"` // Interaction User interaction events (clicks, keydowns, scroll). @@ -3081,6 +3159,9 @@ type BrowserTelemetryCategoriesConfig struct { // Page Page lifecycle events (navigation, load, layout shifts, LCP). Page *BrowserTelemetryCategoryConfig `json:"page,omitempty"` + // Platform Calls that manage the VM rather than drive the browser (recording, filesystem, process, telemetry and browser configuration). Mostly platform-induced; off by default and opt-in. + Platform *BrowserTelemetryCategoryConfig `json:"platform,omitempty"` + // Screenshot Periodic base64-encoded viewport screenshots. High volume; off by default and opt-in. Screenshot *BrowserTelemetryCategoryConfig `json:"screenshot,omitempty"` @@ -3094,7 +3175,7 @@ type BrowserTelemetryCategoryConfig struct { Enabled *bool `json:"enabled,omitempty"` } -// BrowserTelemetryConfig Telemetry configuration for a browser. Selection is opt-in. Omit the browser key (or send an empty object) to capture the default set: lightweight operational signals (control, connection, system, captcha). Within `browser`, only the categories you set enabled: true are captured; anything omitted is off. The CDP categories (console, network, page, interaction) and `screenshot` are off by default and must be opted into. A `browser` config with nothing enabled clears the telemetry configuration. The `monitor` category (CDP collector health) is not configurable here; it flows automatically whenever a CDP category is captured. +// BrowserTelemetryConfig Telemetry configuration for a browser. Selection is opt-in. Omit the browser key (or send an empty object) to capture the default set: lightweight operational signals (control, connection, system, captcha). Within `browser`, only the categories you set enabled: true are captured; anything omitted is off. The CDP categories (console, network, page, interaction), `screenshot` and `platform` are off by default and must be opted into. A `browser` config with nothing enabled clears the telemetry configuration. The `monitor` category (CDP collector health) is not configurable here; it flows automatically whenever a CDP category is captured. type BrowserTelemetryConfig struct { // Browser Per-category telemetry capture settings for browser events. Browser *BrowserTelemetryCategoriesConfig `json:"browser,omitempty"` @@ -3755,7 +3836,7 @@ type TelemetryState struct { // AppliedAt Wall-clock time at which the current configuration was applied. Omitted when telemetry is not configured. AppliedAt *time.Time `json:"applied_at,omitempty"` - // Config Telemetry configuration for a browser. Selection is opt-in. Omit the browser key (or send an empty object) to capture the default set: lightweight operational signals (control, connection, system, captcha). Within `browser`, only the categories you set enabled: true are captured; anything omitted is off. The CDP categories (console, network, page, interaction) and `screenshot` are off by default and must be opted into. A `browser` config with nothing enabled clears the telemetry configuration. The `monitor` category (CDP collector health) is not configurable here; it flows automatically whenever a CDP category is captured. + // Config Telemetry configuration for a browser. Selection is opt-in. Omit the browser key (or send an empty object) to capture the default set: lightweight operational signals (control, connection, system, captcha). Within `browser`, only the categories you set enabled: true are captured; anything omitted is off. The CDP categories (console, network, page, interaction), `screenshot` and `platform` are off by default and must be opted into. A `browser` config with nothing enabled clears the telemetry configuration. The `monitor` category (CDP collector health) is not configurable here; it flows automatically whenever a CDP category is captured. Config BrowserTelemetryConfig `json:"config"` // Seq Process-monotonic sequence number of the last published event. Does not reset across configuration changes. @@ -4742,6 +4823,34 @@ func (t *KnownBrowserTelemetryEvent) MergeBrowserApiCallEvent(v BrowserApiCallEv return err } +// AsBrowserPlatformApiCallEvent returns the union data inside the KnownBrowserTelemetryEvent as a BrowserPlatformApiCallEvent +func (t KnownBrowserTelemetryEvent) AsBrowserPlatformApiCallEvent() (BrowserPlatformApiCallEvent, error) { + var body BrowserPlatformApiCallEvent + err := json.Unmarshal(t.union, &body) + return body, err +} + +// FromBrowserPlatformApiCallEvent overwrites any union data inside the KnownBrowserTelemetryEvent as the provided BrowserPlatformApiCallEvent +func (t *KnownBrowserTelemetryEvent) FromBrowserPlatformApiCallEvent(v BrowserPlatformApiCallEvent) error { + v.Type = "platform_api_call" + b, err := json.Marshal(v) + t.union = b + return err +} + +// MergeBrowserPlatformApiCallEvent performs a merge with any union data inside the KnownBrowserTelemetryEvent, using the provided BrowserPlatformApiCallEvent +func (t *KnownBrowserTelemetryEvent) MergeBrowserPlatformApiCallEvent(v BrowserPlatformApiCallEvent) error { + v.Type = "platform_api_call" + b, err := json.Marshal(v) + if err != nil { + return err + } + + merged, err := runtime.JSONMerge(t.union, b) + t.union = merged + return err +} + // AsBrowserCdpConnectEvent returns the union data inside the KnownBrowserTelemetryEvent as a BrowserCdpConnectEvent func (t KnownBrowserTelemetryEvent) AsBrowserCdpConnectEvent() (BrowserCdpConnectEvent, error) { var body BrowserCdpConnectEvent @@ -5010,6 +5119,8 @@ func (t KnownBrowserTelemetryEvent) ValueByDiscriminator() (interface{}, error) return t.AsBrowserPageNavigationSettledEvent() case "page_tab_opened": return t.AsBrowserPageTabOpenedEvent() + case "platform_api_call": + return t.AsBrowserPlatformApiCallEvent() case "service_crashed": return t.AsBrowserServiceCrashedEvent() case "system_oom_kill": @@ -19258,382 +19369,392 @@ func (sh *strictHandler) StreamTelemetryEvents(w http.ResponseWriter, r *http.Re // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "AA==", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/server/openapi.yaml b/server/openapi.yaml index aa693a1b..20dfdef9 100644 --- a/server/openapi.yaml +++ b/server/openapi.yaml @@ -7,6 +7,7 @@ paths: post: summary: Start a screen recording. Only one recording per ID can be registered at a time. operationId: startRecording + x-telemetry-category: platform requestBody: required: false content: @@ -27,6 +28,7 @@ paths: post: summary: Execute a command synchronously operationId: processExec + x-telemetry-category: platform requestBody: required: true content: @@ -48,6 +50,7 @@ paths: post: summary: Execute a command asynchronously operationId: processSpawn + x-telemetry-category: platform requestBody: required: true content: @@ -69,6 +72,7 @@ paths: get: summary: Get process status operationId: processStatus + x-telemetry-category: platform parameters: - name: process_id in: path @@ -93,6 +97,7 @@ paths: get: summary: Stream process stdout over SSE operationId: processStdoutStream + x-telemetry-category: platform parameters: - name: process_id in: path @@ -123,6 +128,7 @@ paths: post: summary: Write to process stdin operationId: processStdin + x-telemetry-category: platform parameters: - name: process_id in: path @@ -153,6 +159,7 @@ paths: post: summary: Send signal to process operationId: processKill + x-telemetry-category: platform parameters: - name: process_id in: path @@ -183,6 +190,7 @@ paths: post: summary: Resize a PTY-backed process operationId: processResize + x-telemetry-category: platform parameters: - name: process_id in: path @@ -213,6 +221,7 @@ paths: post: summary: Stop the recording operationId: stopRecording + x-telemetry-category: platform requestBody: required: false content: @@ -237,6 +246,7 @@ paths: type: string pattern: "^[a-zA-Z0-9-]+$" operationId: downloadRecording + x-telemetry-category: platform responses: "200": description: Recording file @@ -276,6 +286,7 @@ paths: get: summary: List all recorders operationId: listRecorders + x-telemetry-category: platform responses: "200": description: List of recorders @@ -291,6 +302,7 @@ paths: post: summary: Delete a previously recorded video file operationId: deleteRecording + x-telemetry-category: platform requestBody: required: false content: @@ -315,6 +327,7 @@ paths: Records a named point in time during an active recording. At finalize the markers are injected into the output MP4 as chapter markers. operationId: markRecording + x-telemetry-category: platform requestBody: required: true content: @@ -342,6 +355,7 @@ paths: post: summary: Simulate a mouse click action on the host computer operationId: clickMouse + x-telemetry-category: control requestBody: required: true content: @@ -359,6 +373,7 @@ paths: post: summary: Move the mouse cursor to the specified coordinates on the host computer operationId: moveMouse + x-telemetry-category: control requestBody: required: true content: @@ -376,6 +391,7 @@ paths: post: summary: Capture a screenshot of the host computer operationId: takeScreenshot + x-telemetry-category: control requestBody: required: false content: @@ -398,6 +414,7 @@ paths: post: summary: Hide or show the cursor operationId: setCursor + x-telemetry-category: control requestBody: required: true content: @@ -419,6 +436,7 @@ paths: post: summary: Get the current mouse cursor position on the host computer operationId: getMousePosition + x-telemetry-category: control responses: "200": description: Current mouse position @@ -432,6 +450,7 @@ paths: post: summary: Type text on the host computer operationId: typeText + x-telemetry-category: control requestBody: required: true content: @@ -454,6 +473,7 @@ paths: the X11 keysym definitions at https://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h The server honors millisecond-level durations using fractional sleeps under the hood. operationId: pressKey + x-telemetry-category: control requestBody: required: true content: @@ -476,6 +496,7 @@ paths: When both horizontal and vertical deltas are provided, the server applies them sequentially (vertical then horizontal) and batches wheel events using `xdotool click --repeat N --delay 0