activity-logging
Follow these patterns when implementing activity emission and audit logging in OptAIC. Use for emitting ActivityEnvelopes on mutations (create, update, delete, execute), designing payloads, and ensuring audit compliance.
Best use case
activity-logging is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Follow these patterns when implementing activity emission and audit logging in OptAIC. Use for emitting ActivityEnvelopes on mutations (create, update, delete, execute), designing payloads, and ensuring audit compliance.
Teams using activity-logging should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/activity-logging/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How activity-logging Compares
| Feature / Agent | activity-logging | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Follow these patterns when implementing activity emission and audit logging in OptAIC. Use for emitting ActivityEnvelopes on mutations (create, update, delete, execute), designing payloads, and ensuring audit compliance.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Activity Logging Patterns
Guide for implementing audit-compliant activity emission in OptAIC services.
## When to Use
Apply when:
- Implementing service layer methods that mutate state
- Adding new domain resource operations (CRUD)
- Tracking execution events (runs, training, backtests)
- Implementing approval/promotion workflows
- Ensuring audit trail compliance
## Core Rule
> **If it changes state, it MUST emit an activity.**
All mutations must emit activities in the **service layer** (not API handlers or models).
## ActivityEnvelope
```python
ActivityEnvelope(
tenant_id=UUID,
actor_principal_id=UUID,
resource_id=UUID,
resource_type=str, # "signal", "dataset", "portfolio"
action=str, # "signal.created", "run.completed"
visibility=str, # "private"|"resource"|"scope"|"tenant"
payload=dict, # Action-specific data
delivery_channels=list, # Where to publish
correlation_id=UUID # Links related activities
)
```
## Action Naming
Use pattern: `<resource>.<verb>`
### Core Resource Actions
```
signal.registered signal.validated signal.promoted
dataset.created dataset.previewed dataset.refresh_started
dataset.refresh_completed dataset.refresh_failed
```
### Pipeline Actions
```
pipeline_def.submitted pipeline_def.deployed
pipeline_instance.created pipeline.run_started pipeline.run_completed
```
### Experiment Actions
```
experiment.created experiment.updated
experiment.run_completed experiment.run_failed
expression.evaluated macro.saved
```
### Run Lifecycle Actions
```
run.started run.completed run.failed run.cancelled
backtest.started backtest.completed backtest.failed
training.started training.completed training.failed
inference.started inference.completed inference.failed
optimization.started optimization.completed optimization.failed
monitoring.started monitoring.completed monitoring.alert
```
### Portfolio Actions
```
portfolio.rebalanced portfolio.constraints_updated
portfolio.weights_computed portfolio.optimization_started
```
### Promotion/Workflow Actions
```
promotion.requested promotion.approved promotion.merged promotion.rejected
guardrails.validated guardrails.blocked guardrails.warned
```
### Monitoring Actions
```
monitoring.drift_detected monitoring.performance_alert
monitoring.data_quality_alert monitoring.threshold_breach
```
## Emission Patterns
### Simple Emission
```python
await record_activity_with_outbox(
session=self.session,
envelope=ActivityEnvelope(
action="signal.created",
actor_principal_id=self.actor_id,
tenant_id=self.tenant_id,
resource_id=resource.id,
resource_type="signal",
payload={"signal_type": dto.signal_type}
)
)
```
### Transaction Wrapper
```python
from libs.core.activity import tx_activity
result, activity = await tx_activity(db, envelope, domain_fn)
```
## Payload Guidelines
**Include:** Changed fields, related IDs, computed metrics, status transitions
**Exclude:** Passwords, API keys, large blobs, PII beyond necessity
See [references/payload-examples.md](references/payload-examples.md).
## Correlation IDs
Link related activities in workflows:
```python
correlation_id = uuid4()
# Use same correlation_id throughout workflow
await emit("promotion.requested", correlation_id=correlation_id)
await emit("guardrails.validated", correlation_id=correlation_id)
await emit("promotion.merged", correlation_id=correlation_id)
```
## Real-time Notifications (Outbox Worker)
Activities are processed by the outbox worker which publishes to Centrifugo for real-time WebSocket delivery.
### Notification Types
| Type | Who | Mechanism | Opt-in? |
|------|-----|-----------|---------|
| **Implicit** | Owner + Delegators | Query Resource + RoleBinding | Automatic |
| **Explicit** | Subscribers | Query Subscription table | User opts in |
### Watchers Build Flow
```python
# Outbox worker builds watchers set:
watchers: set[UUID] = set()
# 1. Explicit subscribers (user opt-in)
watchers |= await _subscription_watchers(session, tenant_id, resource_id)
# 2. Resource owner (implicit - auto-notified)
owner_id = await _resource_owner(session, tenant_id, resource_id)
if owner_id:
watchers.add(owner_id)
# 3. Delegators (owner/delegator roles on resource or ancestors)
watchers |= await _resource_delegators(session, tenant_id, resource_id)
# 4. CRITICAL: Exclude actor (don't notify yourself)
watchers.discard(actor_principal_id)
# 5. Filter by user notification preferences
watchers = await _filter_watchers_by_preference(session, tenant_id, watchers, action)
```
### Notification Preferences
Users configure via `PUT /notifications/preferences`:
| Filter Mode | Actions Notified |
|-------------|------------------|
| `all` | All activity types |
| `mutations` (default) | `resource.created/updated/deleted`, `transfer.*`, `promotion.*` |
| `custom` | User-defined patterns (e.g., `["resource.*", "chat.*"]`) |
```python
# Custom pattern matching uses fnmatch
await client.notifications.update_preferences(
filter_mode="custom",
custom_actions=["resource.*", "promotion.*"],
)
```
### Anti-Patterns
| Anti-Pattern | Why It's Wrong | Correct Approach |
|--------------|----------------|------------------|
| Notify actor about own action | Noisy, redundant | Always `watchers.discard(actor_id)` |
| Hardcode notification targets | Inflexible | Build watchers dynamically |
| Skip preference filtering | Users can't control noise | Always filter by preferences |
| Notify without checking roles | Security issue | Use `_resource_delegators()` |
### Subscription API (Explicit Opt-in)
```python
# Subscribe to a resource
await client.subscriptions.create(
resource_id=folder_id,
scope="descendants", # or "resource" for single resource
)
# List subscriptions
subs = await client.subscriptions.list()
# Unsubscribe
await client.subscriptions.revoke(subscription_id)
```
## Reference Files
- [Payload Examples](references/payload-examples.md) - Example payloads by action type
- [Testing Activities](references/testing.md) - How to test activity emissionRelated Skills
siem-logging
Configure security information and event management (SIEM) systems for threat detection, log aggregation, and compliance. Use when implementing centralized security logging, writing detection rules, or meeting audit requirements across cloud and on-premise infrastructure.
fiber-logging-and-project-structure
Applies best practices for logging, project structure, and environment variable usage specifically to the main application file.
assumption-logging
Capture and structure assumptions from pilot plans and hypotheses into a centralized log for ongoing risk monitoring and stakeholder alerts. Use when extracting, tracking, and signaling assumption changes from pilot documentation.
application-logging
Implement structured logging across applications with log aggregation and centralized analysis. Use when setting up application logging, implementing ELK stack, or analyzing application behavior.
sentry-setup-logging
Setup Sentry Logging in any project. Use this when asked to add Sentry logs, enable structured logging, setup console log capture, or integrate logging with Sentry. Supports JavaScript, TypeScript, Python, Ruby, React, Next.js, and other frameworks.
logging-module-usage
Employs the logging module judiciously to log important events, warnings, and errors.
audit_logging
Ensure every critical action is logged (vital for UAG/Trust Room).
activity-log
Display the daily activity log showing all content analyzed today. Use when the user asks what they've watched, read, or analyzed today, mentions activity log, daily log, or wants to see their consumption history.
copilot-thought-logging
See process Copilot is following where you can edit this to reshape the interaction or save when follow up may be needed Triggers on: **
bgo
Automates the complete Blender build-go workflow, from building and packaging your extension/add-on to removing old versions, installing, enabling, and launching Blender for quick testing and iteration.
terraform-engineer
Use when implementing infrastructure as code with Terraform across AWS, Azure, or GCP. Invoke for module development, state management, provider configuration, multi-environment workflows, infrastructure testing.
terraform-diagrams
Generates architecture diagrams from Terraform code. Use when user has .tf files or asks to visualize Terraform infrastructure.