> ## Documentation Index
> Fetch the complete documentation index at: https://docs.equa.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Activity Tracking

> Organization action logging, event audit trail, and task management with exercise-option tracking

# SPEC 022 — Activity Tracking

| Field    | Value                           |
| -------- | ------------------------------- |
| Status   | DRAFT                           |
| Priority | P1 — Core Product               |
| Backend  | `equa-server/modules/activity/` |
| Frontend | `equa-web/src/modules/actions/` |

***

## 1. Feature Purpose

Activity Tracking provides a comprehensive audit trail and action management system for organizations on the Equa platform. It captures three categories of activity: discrete user actions (e.g. cap table edits, document uploads), structured event logs for analytics and compliance, and organizational tasks (e.g. stock option exercises, compliance to-dos). Together these give admins visibility into what happened, when, and by whom — and let stakeholders act on pending items.

***

## 2. Current State (Verified)

### 2.1 Actions

| Detail | Value                                                                |
| ------ | -------------------------------------------------------------------- |
| Entity | `Actions` — records discrete user actions within an organization     |
| Scope  | Organization-level; each action is tied to a user and an action type |
| Usage  | Powers the organization activity feed and feature-request tracking   |

### 2.2 Event Logs

| Detail  | Value                                                       |
| ------- | ----------------------------------------------------------- |
| Entity  | `EventLogs` — generic event journal                         |
| Payload | `data` JSON column holds arbitrary event-specific details   |
| Usage   | Audit trail, analytics pipeline input, compliance reporting |

### 2.3 Tasks

| Detail       | Value                                                                       |
| ------------ | --------------------------------------------------------------------------- |
| Entity       | `Tasks` — tracks actionable items (e.g. option exercises, compliance steps) |
| Composite PK | `(entity, type, status)` — one active task per entity-type combination      |
| Types        | `TaskType` enum (e.g. exercise option, sign agreement, file compliance)     |
| Statuses     | `TaskStatus` enum (e.g. pending, in\_progress, completed, cancelled)        |

### 2.4 Exercise Option Tracking

| Detail       | Value                                                                    |
| ------------ | ------------------------------------------------------------------------ |
| Entity       | `TasksExerciseOption` — captures exercise details for stock option tasks |
| Relationship | Linked to a Task row; stores the selected option hash and share count    |

### 2.5 Backend and Frontend

| Component       | Path                                                          |
| --------------- | ------------------------------------------------------------- |
| Backend module  | `equa-server/modules/activity/`                               |
| Endpoints       | `equa-server/modules/api/src/endpoints/activity-endpoints.ts` |
| Frontend module | `equa-web/src/modules/actions/`                               |

***

## 3. Data Model

### Actions

| Column       | Type      | Constraints                           |
| ------------ | --------- | ------------------------------------- |
| id           | uuid      | PK                                    |
| organization | uuid      | FK → Organizations, NOT NULL          |
| type         | uuid      | FK → action type definition, NOT NULL |
| user         | uuid      | FK → Users, NOT NULL                  |
| createdAt    | timestamp | DEFAULT now()                         |

### EventLogs

| Column       | Type      | Constraints                                                                      |
| ------------ | --------- | -------------------------------------------------------------------------------- |
| id           | uuid      | PK                                                                               |
| type         | varchar   | NOT NULL — event type identifier (e.g. `cap_table.updated`, `document.uploaded`) |
| user         | uuid      | FK → Users, nullable (null for system-generated events)                          |
| organization | uuid      | FK → Organizations, NOT NULL                                                     |
| data         | json      | nullable — event-specific payload                                                |
| createdAt    | timestamp | DEFAULT now()                                                                    |

### Tasks

| Column    | Type       | Constraints                                                         |
| --------- | ---------- | ------------------------------------------------------------------- |
| entity    | uuid       | Composite PK part — the target entity (e.g. grant ID, agreement ID) |
| type      | TaskType   | Composite PK part — enum value identifying the task category        |
| status    | TaskStatus | Composite PK part — enum value for current state                    |
| createdAt | timestamp  | DEFAULT now()                                                       |
| updatedAt | timestamp  | nullable                                                            |

### TasksExerciseOption

| Column | Type    | Constraints                                     |
| ------ | ------- | ----------------------------------------------- |
| id     | uuid    | PK                                              |
| option | Hash    | NOT NULL — identifies the specific option grant |
| shares | numeric | NOT NULL — number of shares being exercised     |

***

## 4. API Endpoints

| Method | Path                                            | Auth | Description                                                           |
| ------ | ----------------------------------------------- | ---- | --------------------------------------------------------------------- |
| GET    | `/api/v1/organizations/:id/actions`             | Yes  | List organization actions (paginated, filterable by type and user)    |
| POST   | `/api/v1/organizations/:id/actions`             | Yes  | Record a new action                                                   |
| GET    | `/api/v1/organizations/:id/actions/:actionId`   | Yes  | Get action details                                                    |
| GET    | `/api/v1/organizations/:id/events`              | Yes  | List event log entries (paginated, filterable by type and date range) |
| GET    | `/api/v1/organizations/:id/tasks`               | Yes  | List tasks (filterable by type and status)                            |
| POST   | `/api/v1/organizations/:id/tasks`               | Yes  | Create a new task                                                     |
| PUT    | `/api/v1/organizations/:id/tasks/:entity/:type` | Yes  | Update task status                                                    |
| GET    | `/api/v1/organizations/:id/tasks/exercises`     | Yes  | List exercise option tasks with details                               |
| POST   | `/api/v1/organizations/:id/tasks/exercises`     | Yes  | Create an exercise option task                                        |

***

## 5. Frontend Components

| Component          | Path                                        | Description                                                      |
| ------------------ | ------------------------------------------- | ---------------------------------------------------------------- |
| ActionsPage        | `actions/ActionsPage.tsx`                   | Organization activity feed with filters for action type and user |
| ActionItem         | `actions/components/ActionItem.tsx`         | Single action row with timestamp, user avatar, and description   |
| TaskList           | `actions/components/TaskList.tsx`           | Pending tasks list with status badges and action buttons         |
| ExerciseOptionForm | `actions/components/ExerciseOptionForm.tsx` | Form for submitting stock option exercise requests               |
| FeatureRequestForm | `actions/components/FeatureRequestForm.tsx` | Form for submitting feature requests (tracked as actions)        |
| ActivityTimeline   | `actions/components/ActivityTimeline.tsx`   | Chronological timeline view of all organization activity         |

### Frontend Behavior

* **Activity feed** — Displays a reverse-chronological list of actions with infinite scroll pagination.
* **Filter bar** — Users can filter by action type, user, and date range; filters update the URL query parameters.
* **Task status transitions** — Status changes trigger optimistic UI updates with rollback on API failure.
* **Exercise option flow** — The exercise form validates share counts against the grant's vested/available balance before submission.
* **Real-time updates** — Activity feed does not auto-refresh; users pull to refresh or navigate away and back.

***

## 6. Business Rules

1. **Immutable actions** — Once recorded, actions cannot be edited or deleted; they serve as an audit trail.
2. **Immutable event logs** — EventLog entries are append-only; no updates or deletes are permitted.
3. **Composite task uniqueness** — The `(entity, type, status)` composite primary key ensures only one active task of a given type exists per entity. Status transitions create new rows rather than updating in place.
4. **Task status machine** — Tasks follow a defined state machine: `pending → in_progress → completed` or `pending → cancelled`. Backward transitions are not allowed.
5. **Exercise validation** — `TasksExerciseOption.shares` must not exceed the vested and unexercised balance of the referenced option grant.
6. **Organization scoping** — All activity queries are scoped to the requesting user's organization; cross-org queries are not supported.
7. **System events** — EventLogs with `user = null` represent system-generated events (e.g. scheduled jobs, automated processes).
8. **Event type conventions** — Event types follow `resource.action` naming (e.g. `cap_table.updated`, `document.uploaded`, `member.invited`).
9. **Action type registry** — Action types are defined by UUID references; new types must be registered before use.
10. **Feature requests** — Feature request actions are a special action type that collects user feedback; they appear in the admin panel (SPEC 019) for review.

***

## 7. Acceptance Criteria

* [ ] Organization activity feed displays actions in reverse chronological order
* [ ] Actions can be filtered by type, user, and date range
* [ ] New actions are recorded with correct user, organization, and type references
* [ ] Actions are immutable — no edit or delete endpoints exist
* [ ] Event logs capture structured event data with correct type and payload
* [ ] Event logs are append-only with no update or delete capability
* [ ] Tasks display with correct status badges (pending, in\_progress, completed, cancelled)
* [ ] Task status transitions follow the defined state machine
* [ ] Backward status transitions are rejected by the API
* [ ] Exercise option tasks validate share count against available vested balance
* [ ] Exercise option form prevents submission when shares exceed available balance
* [ ] Feature requests are recorded as actions and visible in admin panel
* [ ] All activity queries are scoped to the requesting user's organization
* [ ] Pagination works correctly for large activity feeds (100+ items)

***

## 8. Risks

| Risk                                              | Impact                                           | Mitigation                                                                                  |
| ------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| High-volume event logging on active organizations | Database bloat, slow queries                     | Add time-based partitioning on EventLogs; archive old entries to cold storage               |
| Composite PK on Tasks prevents status history     | Cannot audit task state transitions over time    | Log status changes to EventLogs before updating Tasks; consider adding a TaskHistory table  |
| Exercise validation race condition                | Two concurrent exercises exceed available shares | Use database-level locking (SELECT FOR UPDATE) on the option grant during exercise creation |
| No real-time feed updates                         | Users see stale activity data                    | Document manual refresh requirement; consider WebSocket or polling in future iteration      |
| Action type registry requires pre-registration    | Friction when adding new action types            | Provide a seed script; validate type UUIDs at startup                                       |
| EventLogs.data is unstructured JSON               | Inconsistent payloads, difficult querying        | Define JSON schemas per event type; validate payloads before insert                         |
| Cross-org data leak via malformed query           | Sensitive activity visible to wrong organization | Enforce organization scoping in repository layer; add integration tests for isolation       |
| Large exercise option numeric values              | Precision loss on share counts                   | Use `numeric` type (arbitrary precision); validate reasonable bounds on input               |
