# Activity Logging API

The Activity Logging API provides comprehensive audit trail and activity tracking functionality for the Mosaic Stack platform. It logs user actions, workspace changes, task/event modifications, and authentication events.

## Overview

Activity logs are automatically created for:

- **CRUD Operations**: Task, event, project, and workspace modifications
- **Authentication Events**: Login, logout, password resets
- **User Actions**: Task assignments, workspace member changes
- **System Events**: Configuration updates, permission changes

All activity logs are workspace-scoped and support multi-tenant isolation through Row-Level Security (RLS).

## Endpoints

### List Activity Logs

```
GET /api/activity
```

Get a paginated list of activity logs with optional filters.

**Query Parameters:**

| Parameter     | Type           | Required | Description                                    |
| ------------- | -------------- | -------- | ---------------------------------------------- |
| `workspaceId` | UUID           | Yes      | Workspace to filter by                         |
| `userId`      | UUID           | No       | Filter by user who performed the action        |
| `action`      | ActivityAction | No       | Filter by action type (CREATED, UPDATED, etc.) |
| `entityType`  | EntityType     | No       | Filter by entity type (TASK, EVENT, etc.)      |
| `entityId`    | UUID           | No       | Filter by specific entity                      |
| `startDate`   | ISO 8601       | No       | Filter activities after this date              |
| `endDate`     | ISO 8601       | No       | Filter activities before this date             |
| `page`        | Number         | No       | Page number (default: 1)                       |
| `limit`       | Number         | No       | Items per page (default: 50, max: 100)         |

**Response:**

```json
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "workspaceId": "660e8400-e29b-41d4-a716-446655440001",
      "userId": "770e8400-e29b-41d4-a716-446655440002",
      "action": "CREATED",
      "entityType": "TASK",
      "entityId": "880e8400-e29b-41d4-a716-446655440003",
      "details": {
        "title": "New Task",
        "status": "NOT_STARTED"
      },
      "ipAddress": "192.168.1.1",
      "userAgent": "Mozilla/5.0...",
      "createdAt": "2024-01-28T12:00:00Z",
      "user": {
        "id": "770e8400-e29b-41d4-a716-446655440002",
        "name": "John Doe",
        "email": "john@example.com"
      }
    }
  ],
  "meta": {
    "total": 150,
    "page": 1,
    "limit": 50,
    "totalPages": 3
  }
}
```

**Example Requests:**

```bash
# Get all activities in a workspace
GET /api/activity?workspaceId=660e8400-e29b-41d4-a716-446655440001

# Get activities for a specific user
GET /api/activity?workspaceId=660e8400-e29b-41d4-a716-446655440001&userId=770e8400-e29b-41d4-a716-446655440002

# Get task creation events
GET /api/activity?workspaceId=660e8400-e29b-41d4-a716-446655440001&action=CREATED&entityType=TASK

# Get activities in date range
GET /api/activity?workspaceId=660e8400-e29b-41d4-a716-446655440001&startDate=2024-01-01&endDate=2024-01-31

# Paginate results
GET /api/activity?workspaceId=660e8400-e29b-41d4-a716-446655440001&page=2&limit=25
```

---

### Get Single Activity Log

```
GET /api/activity/:id
```

Retrieve a single activity log entry by ID.

**Path Parameters:**

| Parameter | Type | Required | Description     |
| --------- | ---- | -------- | --------------- |
| `id`      | UUID | Yes      | Activity log ID |

**Query Parameters:**

| Parameter     | Type | Required | Description                               |
| ------------- | ---- | -------- | ----------------------------------------- |
| `workspaceId` | UUID | Yes      | Workspace ID (for multi-tenant isolation) |

**Response:**

```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "workspaceId": "660e8400-e29b-41d4-a716-446655440001",
  "userId": "770e8400-e29b-41d4-a716-446655440002",
  "action": "UPDATED",
  "entityType": "TASK",
  "entityId": "880e8400-e29b-41d4-a716-446655440003",
  "details": {
    "changes": {
      "status": "IN_PROGRESS"
    }
  },
  "ipAddress": "192.168.1.1",
  "userAgent": "Mozilla/5.0...",
  "createdAt": "2024-01-28T12:00:00Z",
  "user": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "name": "John Doe",
    "email": "john@example.com"
  }
}
```

**Example Request:**

```bash
GET /api/activity/550e8400-e29b-41d4-a716-446655440000?workspaceId=660e8400-e29b-41d4-a716-446655440001
```

---

### Get Entity Audit Trail

```
GET /api/activity/audit/:entityType/:entityId
```

Retrieve complete audit trail for a specific entity (task, event, project, etc.).

**Path Parameters:**

| Parameter    | Type       | Required | Description                                            |
| ------------ | ---------- | -------- | ------------------------------------------------------ |
| `entityType` | EntityType | Yes      | Type of entity (TASK, EVENT, PROJECT, WORKSPACE, USER) |
| `entityId`   | UUID       | Yes      | Entity ID                                              |

**Query Parameters:**

| Parameter     | Type | Required | Description                               |
| ------------- | ---- | -------- | ----------------------------------------- |
| `workspaceId` | UUID | Yes      | Workspace ID (for multi-tenant isolation) |

**Response:**

Returns array of activity logs in chronological order (oldest first).

```json
[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "workspaceId": "660e8400-e29b-41d4-a716-446655440001",
    "userId": "770e8400-e29b-41d4-a716-446655440002",
    "action": "CREATED",
    "entityType": "TASK",
    "entityId": "880e8400-e29b-41d4-a716-446655440003",
    "details": {
      "title": "New Task"
    },
    "createdAt": "2024-01-28T10:00:00Z",
    "user": {
      "id": "770e8400-e29b-41d4-a716-446655440002",
      "name": "John Doe",
      "email": "john@example.com"
    }
  },
  {
    "id": "660e8400-e29b-41d4-a716-446655440004",
    "workspaceId": "660e8400-e29b-41d4-a716-446655440001",
    "userId": "770e8400-e29b-41d4-a716-446655440005",
    "action": "UPDATED",
    "entityType": "TASK",
    "entityId": "880e8400-e29b-41d4-a716-446655440003",
    "details": {
      "changes": {
        "status": "IN_PROGRESS"
      }
    },
    "createdAt": "2024-01-28T12:00:00Z",
    "user": {
      "id": "770e8400-e29b-41d4-a716-446655440005",
      "name": "Jane Smith",
      "email": "jane@example.com"
    }
  }
]
```

**Example Requests:**

```bash
# Get audit trail for a task
GET /api/activity/audit/TASK/880e8400-e29b-41d4-a716-446655440003?workspaceId=660e8400-e29b-41d4-a716-446655440001

# Get audit trail for a project
GET /api/activity/audit/PROJECT/990e8400-e29b-41d4-a716-446655440006?workspaceId=660e8400-e29b-41d4-a716-446655440001

# Get audit trail for a workspace
GET /api/activity/audit/WORKSPACE/660e8400-e29b-41d4-a716-446655440001?workspaceId=660e8400-e29b-41d4-a716-446655440001
```

---

## Enums

### ActivityAction

Actions that can be logged:

- `CREATED` - Entity was created
- `UPDATED` - Entity was updated
- `DELETED` - Entity was deleted
- `COMPLETED` - Task or project was completed
- `ASSIGNED` - Task was assigned to a user
- `COMMENTED` - Comment was added (future use)
- `LOGIN` - User logged in
- `LOGOUT` - User logged out
- `PASSWORD_RESET` - Password was reset
- `EMAIL_VERIFIED` - Email was verified

### EntityType

Types of entities that can be tracked:

- `TASK` - Task entity
- `EVENT` - Calendar event
- `PROJECT` - Project
- `WORKSPACE` - Workspace
- `USER` - User profile

---

## Automatic Logging

The Activity Logging system includes an interceptor that automatically logs:

- **POST requests** → `CREATED` action
- **PATCH/PUT requests** → `UPDATED` action
- **DELETE requests** → `DELETED` action

The interceptor extracts:

- User information from the authenticated session
- Workspace context from request
- IP address and user agent from HTTP headers
- Entity ID from route parameters or response

---

## Manual Logging

For custom logging scenarios, use the `ActivityService` helper methods:

```typescript
import { ActivityService } from "@/activity/activity.service";

@Injectable()
export class TaskService {
  constructor(private activityService: ActivityService) {}

  async createTask(data, userId, workspaceId) {
    const task = await this.prisma.task.create({ data });

    // Log task creation
    await this.activityService.logTaskCreated(workspaceId, userId, task.id, { title: task.title });

    return task;
  }
}
```

### Available Helper Methods

#### Task Activities

- `logTaskCreated(workspaceId, userId, taskId, details?)`
- `logTaskUpdated(workspaceId, userId, taskId, details?)`
- `logTaskDeleted(workspaceId, userId, taskId, details?)`
- `logTaskCompleted(workspaceId, userId, taskId, details?)`
- `logTaskAssigned(workspaceId, userId, taskId, assigneeId)`

#### Event Activities

- `logEventCreated(workspaceId, userId, eventId, details?)`
- `logEventUpdated(workspaceId, userId, eventId, details?)`
- `logEventDeleted(workspaceId, userId, eventId, details?)`

#### Project Activities

- `logProjectCreated(workspaceId, userId, projectId, details?)`
- `logProjectUpdated(workspaceId, userId, projectId, details?)`
- `logProjectDeleted(workspaceId, userId, projectId, details?)`

#### Workspace Activities

- `logWorkspaceCreated(workspaceId, userId, details?)`
- `logWorkspaceUpdated(workspaceId, userId, details?)`
- `logWorkspaceMemberAdded(workspaceId, userId, memberId, role)`
- `logWorkspaceMemberRemoved(workspaceId, userId, memberId)`

#### User Activities

- `logUserUpdated(workspaceId, userId, details?)`

---

## Security & Privacy

### Multi-Tenant Isolation

All activity logs are scoped to workspaces using Row-Level Security (RLS). Users can only access activity logs for workspaces they belong to.

### Data Retention

Activity logs are retained indefinitely by default. Consider implementing a retention policy based on:

- Compliance requirements
- Storage constraints
- Business needs

### Sensitive Data

Activity logs should NOT contain:

- Passwords or authentication tokens
- Credit card information
- Personal health information
- Other sensitive PII

Store only metadata needed for audit purposes. Use the `details` field for non-sensitive context.

---

## Best Practices

### 1. Use Descriptive Details

Include enough context to understand what changed:

```typescript
// Good
await activityService.logTaskUpdated(workspaceId, userId, taskId, {
  changes: {
    status: { from: "NOT_STARTED", to: "IN_PROGRESS" },
    assignee: { from: null, to: "user-456" },
  },
});

// Less useful
await activityService.logTaskUpdated(workspaceId, userId, taskId);
```

### 2. Log Business-Critical Actions

Prioritize logging actions that:

- Change permissions or access control
- Delete data
- Modify billing or subscription
- Export data
- Change security settings

### 3. Query Efficiently

Use appropriate filters to reduce data transfer:

```typescript
// Efficient - filters at database level
const activities = await fetch("/api/activity?workspaceId=xxx&entityType=TASK&page=1&limit=50");

// Inefficient - transfers all data then filters
const activities = await fetch("/api/activity?workspaceId=xxx");
const taskActivities = activities.filter((a) => a.entityType === "TASK");
```

### 4. Display User-Friendly Activity Feeds

Transform activity logs into human-readable messages:

```typescript
function formatActivityMessage(activity: ActivityLog) {
  const { user, action, entityType, details } = activity;

  switch (action) {
    case "CREATED":
      return `${user.name} created ${entityType.toLowerCase()} "${details.title}"`;
    case "UPDATED":
      return `${user.name} updated ${entityType.toLowerCase()}`;
    case "DELETED":
      return `${user.name} deleted ${entityType.toLowerCase()}`;
    default:
      return `${user.name} performed ${action}`;
  }
}
```

---

## Error Handling

Activity logging failures should NOT block the primary operation. The interceptor and service methods handle errors gracefully:

```typescript
try {
  await activityService.logActivity(data);
} catch (error) {
  // Log error but don't throw
  logger.error("Failed to log activity", error);
}
```

If activity logging is critical for compliance, implement synchronous validation before the operation completes.

---

## Performance Considerations

### Indexing

The following indexes optimize common queries:

- `workspaceId` - Filter by workspace
- `workspaceId + createdAt` - Recent activities per workspace
- `entityType + entityId` - Audit trail queries
- `userId` - User activity history
- `action` - Filter by action type

### Pagination

Always use pagination for activity queries. Default limit is 50 items, maximum is 100.

### Background Processing

For high-volume systems, consider:

- Async activity logging with message queues
- Batch inserts for multiple activities
- Separate read replicas for reporting

---

## Related Documentation

- [Authentication API](../2-authentication/README.md)
- [API Conventions](../1-conventions/README.md)
- [Database Schema](../../3-architecture/2-database/README.md)
