From datum-platform
Covers activity timeline integration using the Activity system. Use when implementing ActivityPolicy resources, emitting Kubernetes events for activity tracking, or exposing activity timelines to users via CLI, UI, or API.
npx claudepluginhub datum-cloud/claude-code-plugins --plugin datum-platformThis skill uses the workspace's default tool permissions.
This skill covers activity timeline integration for Datum Cloud services using the Activity system.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
This skill covers activity timeline integration for Datum Cloud services using the Activity system.
The Activity system is a declarative, policy-driven, Kubernetes-native platform for transforming raw audit logs and Kubernetes events into human-readable activity timelines. It provides:
Key insight: Services don't emit activity events directly. Instead, services define ActivityPolicy resources that describe how their resource operations should appear in activity timelines.
All activity resources use the activity.miloapis.com API group with version v1alpha1.
The activity system has six resource types:
| Resource | Scope | Purpose |
|---|---|---|
| Activity | Read-only | Human-readable activity record (query result) |
| ActivityPolicy | Cluster | Defines translation rules for resource types |
| ActivityQuery | Ephemeral | Search historical activities with filters |
| ActivityFacetQuery | Ephemeral | Get distinct values for filter dropdowns |
| AuditLogQuery | Ephemeral | Query raw audit log entries directly |
| AuditLogFacetsQuery | Ephemeral | Get facets from raw audit logs |
| PolicyPreview | Ephemeral | Test policies against sample inputs |
Read concepts.md for detailed explanations of each resource type.
Read emitting-events.md for how controllers should emit Kubernetes events.
Read consuming-timelines.md for how to expose activity timelines to users.
Services integrate by creating ActivityPolicy resources that define how their API operations appear in activity feeds. The activity system automatically:
emitting-events.md)apiVersion: activity.miloapis.com/v1alpha1
kind: ActivityPolicy
metadata:
name: myservice-myresource
spec:
resource:
apiGroup: myservice.miloapis.com
kind: MyResource
auditRules:
- match: "audit.verb == 'create'"
summary: "{{ actor }} created {{ link(kind + ' ' + audit.objectRef.name, audit.responseObject) }}"
- match: "audit.verb == 'delete'"
summary: "{{ actor }} deleted {{ kind }} {{ audit.objectRef.name }}"
- match: "audit.verb in ['update', 'patch']"
summary: "{{ actor }} updated {{ link(kind + ' ' + audit.objectRef.name, audit.objectRef) }}"
eventRules:
- match: "event.reason == 'Ready'"
summary: "{{ link(kind + ' ' + event.regarding.name, event.regarding) }} is now ready"
# config/apiserver/policies/kustomization.yaml
resources:
- myresource-policy.yaml
apiVersion: activity.miloapis.com/v1alpha1
kind: PolicyPreview
spec:
policy:
resource:
apiGroup: myservice.miloapis.com
kind: MyResource
auditRules:
- match: "audit.verb == 'create'"
summary: "{{ actor }} created MyResource"
inputs:
- type: audit
audit:
verb: create
objectRef:
apiGroup: myservice.miloapis.com
resource: myresources
name: my-resource
user:
username: alice@example.com
The translated activity record that users see:
apiVersion: activity.miloapis.com/v1alpha1
kind: Activity
metadata:
name: activity-abc123
spec:
summary: "alice@example.com created MyResource my-resource"
changeSource: human # "human" or "system"
actor:
type: user # user, serviceaccount, controller
name: alice@example.com
email: alice@example.com
resource:
apiGroup: myservice.miloapis.com
kind: MyResource
name: my-resource
namespace: my-project
links:
- marker: "MyResource my-resource"
resource:
apiGroup: myservice.miloapis.com
kind: MyResource
name: my-resource
tenant:
type: project
name: my-project
origin:
type: audit
id: abc123-audit-id
changes: # Optional field-level diffs
- field: "spec.replicas"
old: "1"
new: "3"
| Type | Description | Example |
|---|---|---|
user | Human user via UI/CLI | alice@example.com |
serviceaccount | Kubernetes service account | system:serviceaccount:default:mysa |
controller | Kubernetes controller | deployment-controller |
| Value | Meaning |
|---|---|
human | User-initiated via UI, CLI, or API |
system | Controller or automation initiated |
Services can help users understand activity through multiple interfaces. Read consuming-timelines.md for complete patterns.
The most user-friendly way to query activities:
# Query recent activity (default: last 24 hours)
kubectl activity query
# Search last 7 days for human changes
kubectl activity query --start-time "now-7d" --filter "spec.changeSource == 'human'"
# Filter by resource kind
kubectl activity query --filter "spec.resource.kind == 'HTTPProxy'"
# JSON output for scripting
kubectl activity query -o json
# Pagination
kubectl activity query --limit 50 --continue-after "eyJhbGciOiJ..."
# Stream new activities in real-time
kubectl get activities --watch
# Filter by change source
kubectl get activities --watch --field-selector spec.changeSource=human
apiVersion: activity.miloapis.com/v1alpha1
kind: ActivityQuery
metadata:
name: recent-changes
spec:
startTime: "now-7d" # Relative: now-{n}{s|m|h|d|w}
endTime: "now" # Or absolute: 2024-01-01T00:00:00Z
changeSource: "human" # Optional: human or system
namespace: "my-project" # Optional: filter by namespace
resourceKind: "MyResource" # Optional: filter by kind
actorName: "alice@example.com" # Optional: filter by actor
search: "created" # Optional: full-text search
filter: "spec.actor.type == 'user'" # Optional: CEL expression
limit: 100 # Pagination (max 1000)
apiVersion: activity.miloapis.com/v1alpha1
kind: ActivityFacetQuery
spec:
timeRange:
start: "now-30d"
filter: "spec.changeSource == 'human'"
facets:
- field: spec.actor.name
limit: 20
- field: spec.resource.kind
- field: spec.resource.namespace
Returns:
status:
facets:
- field: spec.actor.name
values:
- value: alice@example.com
count: 142
- value: bob@example.com
count: 89
- field: spec.resource.kind
values:
- value: MyResource
count: 231
Pure CEL returning boolean:
# Audit log variables
audit.verb == 'create'
audit.verb in ['update', 'patch']
audit.objectRef.subresource == 'status'
audit.objectRef.subresource == 'scale'
audit.user.username.startsWith('system:')
audit.responseStatus.code >= 400
# Event variables
event.reason == 'Ready'
event.type == 'Warning'
event.regarding.name == 'my-resource'
CEL expressions in {{ }} delimiters:
# Built-in helpers
summary: "{{ actor }} created {{ kind }}"
# link(displayText, resourceRef) - creates clickable reference
summary: "{{ link(kind + ' ' + audit.objectRef.name, audit.responseObject) }}"
# Conditional text
summary: "{{ audit.user.username.startsWith('system:') ? 'System' : actor }} updated {{ kind }}"
| Context | Variable | Description |
|---|---|---|
| Audit | audit | Full audit.Event object |
| Audit | audit.verb | API verb (create, update, delete, etc.) |
| Audit | audit.objectRef | Target resource reference |
| Audit | audit.user | Authenticated user info |
| Audit | audit.responseObject | Created/updated object |
| Audit | audit.responseStatus | Response status |
| Event | event | Full core/v1 Event object |
| Event | event.reason | Event reason code |
| Event | event.type | Normal or Warning |
| Event | event.regarding | Resource the event is about |
| Both | actor | Resolved actor display name |
| Both | kind | Resource kind from spec |
Read implementation.md for:
Run scripts/validate-activity.sh to verify:
concepts.md — Activity domain model detailsemitting-events.md — How controllers emit Kubernetes events for activityimplementation.md — Integration guide with examples (creating ActivityPolicies)consuming-timelines.md — How to expose activity timelines to usersscripts/validate-activity.sh — Validation scriptscripts/scaffold-activity.sh — Policy scaffolding script