<#871 Wire Redis activity rollups through to the f...
# osctrl
g
#871 Wire Redis activity rollups through to the frontend Pull request opened by javuto Summary The Redis-backed activity store (
pkg/activity
) was added recently but was dead plumbing:
osctrl-tls
constructed an
ActivityWriter
and wired it onto the service handler, but no endpoint ever called
addEvent
, so the per-endpoint hourly rollups (enroll / config / status / result / query-read / query-write) were never written. The API never read the store either — the SPA's activity heatmaps are served from DB bucket queries — so the finer-grained series (the config fetches and the query read/write split that the DB buckets collapse into a single
query
category) were never displayed. This wires the store end-to-end so the per-endpoint last-seen activity shows in the frontend. Changes osctrl-tls — feed the store • Added a nil-safe, fire-and-forget
recordActivity(envUUID, nodeUUID, type)
helper on
HandlersTLS
plus
logActivityType()
to map osquery log types. • Emit
activity.Event
at every osquery endpoint in `cmd/tls/handlers/post.go`: •
EnrollHandler
EventEnroll
(guarded by
!nodeInvalid
) •
ConfigHandler
EventConfig
LogHandler
EventStatus
/
EventResult
via
logActivityType
(unknown log types are skipped, never recorded) •
QueryReadHandler
EventQueryRead
QueryWriteHandler
EventQueryWrite
• Carve endpoints are intentionally excluded: there is no carve
EventType
, and inventing one would change the Redis bit layout /
EventTypeCount
. osctrl-api — expose the series
cmd/api
already held a Redis client; added an
*activity.RedisStore
reader using the same prefix and retention as TLS so reads match writes. • Two new additive endpoints, both behind the existing JWT auth + per-env
UserLevel
permission + node/env membership checks: •
GET /api/v1/stats/activity/node-tiles/{env}/{uuid}?days=N
activity.NodeTileSeries
GET /api/v1/stats/activity/env-tiles/{env}?days=N
activity.EnvSeries
?days
defaults to 1 and clamps to `DefaultRetentionDays`; returns
503
when the activity store is not configured (not
500
). • Existing DB-backed
/stats/activity/...
endpoints and their SPA consumers are unchanged. Frontend — display per-endpoint last-seen • `src/api/stats.ts`:
NodeTileSeries
type,
getNodeActivityTiles
/
getEnvActivityTiles
fetchers, and
tileLastSeen
/
tileCategoryTotal
helpers. • `src/features/nodes/NodeDetailPage.tsx`: new "Endpoint activity · last 24h" panel under the existing heatmap, showing each of config / status / result / query-read / query-write with its event total and a relative last-seen timestamp. Last-seen granularity is hourly (the Redis rollup bucket size). Behavior / risk notes • The activity write path is non-blocking:
addEvent
drops on a full queue (existing behavior) and
recordActivity
no-ops on a nil writer or empty env/node UUIDs, so it can never fail or stall a TLS request. • Security-sensitive TLS handlers are touched only additively (one fire-and-forget call each after the existing last-seen batch update); no request parsing, auth, or response logic changed. •
go.mod
/
go.sum
are untouched. Validation
go build ./cmd/...
— clean. •
go test ./cmd/tls/handlers/...
(activity tests):
TestRecordActivityEmitsTypedEvent
,
TestRecordActivityIsNoopWhenNotConfiguredOrMissingIDs
,
TestLogActivityTypeMapping
— pass. •
go test ./cmd/api/handlers/...
(tile tests):
TestActivityTileDays
,
TestNodeTileSeriesJSONShape
— pass. •
go test ./pkg/activity/...
— pass. • Frontend
tsc --noEmit
— clean;
NodeDetailPage.test.tsx
— pass (mock updated to stub the new tiles fetch). Pre-existing failures unrelated to this change (reproduce without these edits, in untouched files): `LoginPage`/`ProfilePage` SPA tests fail on
localStorage
under jsdom, and the Go `auth_oidc`/`auth_logout` tests panic in
httptest.NewServer
under the sandbox network restriction. Out of scope / follow-ups • A carve activity type (and carve last-seen) would require a new
EventType
and a Redis blob layout change; deferred. • The env-tiles endpoint is wired and tested but not yet rendered in the SPA dashboard; the node-tiles panel is the user-facing surface added here. jmpsec/osctrl