> ## 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.

# Reports

> Holder reports, pools reports, and holdings reports derived from cap table data

# SPEC 014 — Reports

| Field    | Value                                                                                        |
| -------- | -------------------------------------------------------------------------------------------- |
| Status   | DRAFT                                                                                        |
| Priority | P1 — Core Platform                                                                           |
| Backend  | None dedicated — data sourced from cap table, ESOP, and holdings entities via shared loaders |
| Frontend | `equa-web/src/modules/reports/`                                                              |

***

## 1. Feature Purpose

Reports provide organization administrators and stakeholders with tabular views of cap table data. Three report types are available: Holder Report (per-member ownership summary), Pools Report (option pool and convertible instrument utilization), and Holdings Report (individual certificate-level detail). All reports support dynamic filtering, sortable columns, and footer totals. Reports are read-only views over existing cap table data — no dedicated backend module exists.

***

## 2. Current State (Verified)

### 2.1 Holder Report

| Detail        | Value                                                                                                                     |
| ------------- | ------------------------------------------------------------------------------------------------------------------------- |
| File          | `equa-web/src/modules/reports/pages/holder-report.tsx`                                                                    |
| Component     | `HolderReportsPage`                                                                                                       |
| Data loader   | `loadCaptableData('false')`                                                                                               |
| Permission    | `BuiltInPermission.viewCapTable` OR `BuiltInPermission.viewSelf`                                                          |
| HOC chain     | `withPermissions` → `withLoadingCachedMultiple`                                                                           |
| Columns       | Holder (avatar + name link), Investment (USD), Outstanding (shares), Ownership (%), Fully Diluted (shares), Ownership (%) |
| Footer        | Row totals across all columns                                                                                             |
| Row filtering | Excludes members with no holdings and no voided records                                                                   |
| Page size     | 100,000 (effectively unbounded)                                                                                           |
| Member link   | Opens in new tab via `organizationMemberPath`                                                                             |

### 2.2 Pools Report

| Detail           | Value                                                                                                       |
| ---------------- | ----------------------------------------------------------------------------------------------------------- |
| File             | `equa-web/src/modules/reports/pages/pools-report.tsx`                                                       |
| Component        | `PoolsReportsPage`                                                                                          |
| Data loader      | `loadCaptablePools`                                                                                         |
| Permission       | `BuiltInPermission.viewCapTable` OR `BuiltInPermission.viewSelf`                                            |
| Columns          | Pool (name link), Equity (link), Type, Authorized, Treasury, Investment (USD), Fully Diluted, Ownership (%) |
| Filters          | Equity (dynamic from pool data), Type (`Incentive` / `Convertible`)                                         |
| Filter component | `dynamicFilter` shared component                                                                            |
| Footer           | Row totals for Authorized, Treasury, Investment, Fully Diluted, Ownership                                   |
| Pool link        | Links to `poolPath` for incentive pools, `viewConvertibleInstrumentPath` for convertibles                   |

### 2.3 Holdings Report

| Detail      | Value                                                                                                                                                             |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| File        | `equa-web/src/modules/reports/pages/holdings-report.tsx`                                                                                                          |
| Component   | `HoldingsReportsPage`                                                                                                                                             |
| Data loader | `loadQueryData`                                                                                                                                                   |
| Permission  | `BuiltInPermission.viewCapTable` OR `BuiltInPermission.viewSelf`                                                                                                  |
| Columns     | Cert ID (certificate image + link), Holder (link), Class, # (index), Type, Issue Date, Investment (USD), Outstanding, Ownership (%), Fully Diluted, Ownership (%) |
| Filters     | Holder (dynamic), Class (dynamic), Type (dynamic)                                                                                                                 |
| Exclusions  | Convertible instruments, pools, and org assets are filtered out of the holdings list                                                                              |
| Footer      | Row totals for Investment, Outstanding, Ownership, Fully Diluted, Ownership                                                                                       |

### 2.4 Module Exports

| File             | Exports                                                                                      |
| ---------------- | -------------------------------------------------------------------------------------------- |
| `pages/index.ts` | `HolderReportsPage`, `PoolsReportsPage`, `HoldingsReportsPage` (re-exported from page files) |
| `index.ts`       | Re-exports all pages                                                                         |

***

## 3. Data Model

Reports do not maintain their own data model. They consume data from:

### Source: Cap Table Dashboard (`GetCaptableDashboardResponse`)

| Field     | Type                                                                                                                                                              | Used in       |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `members` | Array of member records with `holdings`, `voided`, `memberInvestment`, `memberOutstanding`, `memberOutstandingPer`, `memberFullyDiluted`, `memberFullyDilutedPer` | Holder Report |

### Source: Pools Report (`GetPoolsReportResponse`)

| Field   | Type                                                                                                                                           | Used in      |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| `pools` | Array with `name`, `equity`, `equityName`, `internalType`, `authorized`, `treasury`, `investment`, `fullyDiluted`, `ownership`, `plan`, `hash` | Pools Report |

### Source: Holdings Query (`QueryResponse`)

| Field     | Type                                                                                                                                                                                                   | Used in         |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------- |
| `holding` | Array with `name`, `holderName`, `class`, `internalType`, `issueDate`, `capitalContribution`, `outstanding`, `outstandingPercentage`, `fullyDiluted`, `fullyDilutedPercentage`, `holdingType`, `owner` | Holdings Report |

### Enums Referenced

| Enum                | Values                                                                      | Used in                |
| ------------------- | --------------------------------------------------------------------------- | ---------------------- |
| `HoldingRecordType` | `convertibleInstrument`, `pool`, `orgAsset` (excluded from holdings report) | Holdings Report filter |
| `BuiltInPermission` | `viewCapTable`, `viewSelf`                                                  | All reports            |

***

## 4. API Endpoints

Reports consume existing cap table endpoints — no dedicated report endpoints exist.

| Method | Path                                                    | Auth                 | Description                               | Used by         |
| ------ | ------------------------------------------------------- | -------------------- | ----------------------------------------- | --------------- |
| GET    | `/api/v1/organization/:organization/captable/dashboard` | Session + permission | Cap table member summary                  | Holder Report   |
| GET    | `/api/v1/organization/:organization/captable/pools`     | Session + permission | Pool summary data                         | Pools Report    |
| GET    | `/api/v1/organization/:organization/captable/query`     | Session + permission | Individual holdings with certificate data | Holdings Report |

***

## 5. Frontend Components

### Module: `equa-web/src/modules/reports/`

| Component             | File                        | Purpose                                                                         |
| --------------------- | --------------------------- | ------------------------------------------------------------------------------- |
| `HolderReportsPage`   | `pages/holder-report.tsx`   | Table of holders with investment, outstanding, ownership, fully diluted         |
| `PoolsReportsPage`    | `pages/pools-report.tsx`    | Table of option pools and convertible instruments with utilization metrics      |
| `HoldingsReportsPage` | `pages/holdings-report.tsx` | Table of individual holdings/certificates with filtering by holder, class, type |

### Shared Dependencies

| Component                           | Source                              | Purpose                                                |
| ----------------------------------- | ----------------------------------- | ------------------------------------------------------ |
| `Table`                             | `@components/tables/table`          | Base table component with sorting, pagination, borders |
| `dynamicFilter`                     | `@shared/components/dynamic-filter` | Creates filter dropdowns from data                     |
| `PathLink`                          | `@components/navigation`            | Navigation links to member/security/pool pages         |
| `Avatar`                            | `@components/avatar`                | Member avatar in holder report rows                    |
| `CertificateLink`                   | `@modules/captable/components`      | Certificate image + link in holdings report            |
| `withPermissions`                   | `@shared/hocs/with-permissions`     | Permission guard HOC                                   |
| `withLoadingCachedMultiple`         | `@components/loading`               | Data loading with caching                              |
| `PageContent` / `PageContentHeader` | `@components/pages`                 | Page layout wrappers                                   |

***

## 6. Business Rules

1. **Permission gating**: All three reports require either `viewCapTable` or `viewSelf` permission. Users with `viewSelf` see only their own holdings in the data.
2. **Holder Report** excludes members who have no holdings AND no voided records (i.e., members with zero equity involvement are hidden).
3. **Holdings Report** excludes records of type `convertibleInstrument`, `pool`, and `orgAsset` — these appear in their own dedicated views.
4. **Pools Report** classifies pools as either `Incentive` (ESOP plans) or `Convertible` (convertible instruments).
5. **Ownership percentages** are displayed to 2 decimal places (`.toFixed(2)`).
6. **Investment values** are formatted as USD using `optionalUsdString`.
7. **Share counts** use `toCommaFloat` for comma-separated formatting.
8. **Footer totals** aggregate across all visible rows (post-filter).
9. **All links** from reports open in a new browser tab (`target='_blank'`).
10. **Page size** is set to 100,000 across all reports — effectively no client-side pagination.

***

## 7. Acceptance Criteria

* [ ] Holder Report displays all members with equity involvement, with correct investment, outstanding, ownership, and fully diluted values
* [ ] Holder Report footer shows accurate totals for all numeric columns
* [ ] Pools Report displays incentive pools and convertible instruments with correct metrics
* [ ] Pools Report filter by Equity and Type works correctly
* [ ] Holdings Report displays individual certificates with all metadata fields
* [ ] Holdings Report filter by Holder, Class, and Type works correctly
* [ ] All percentage columns display 2 decimal places
* [ ] All USD columns are properly formatted
* [ ] Links to members, securities, pools, and certificates open in new tabs
* [ ] Users without `viewCapTable` or `viewSelf` permission cannot access reports
* [ ] Reports load successfully for organizations with large cap tables (1000+ holdings)

***

## 8. Risks

| Risk                                                      | Impact                                                                  | Mitigation                                                                                                      |
| --------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| No server-side pagination (page size 100,000)             | Browser performance with very large cap tables                          | Implement server-side pagination or virtual scrolling for 1000+ rows                                            |
| No CSV/PDF export                                         | Users must screenshot or copy data manually                             | Add export functionality (referenced in platform feature list but not yet implemented in reports module)        |
| Permission check uses OR logic (viewCapTable OR viewSelf) | viewSelf users may see aggregate totals that reveal other holders' data | Ensure server filters response data to only the requesting user's holdings when viewSelf is the sole permission |
| Reports pull full cap table data on each page load        | Redundant API calls when switching between report types                 | Shared data cache across report pages within same session                                                       |
| No date range filtering                                   | Cannot view historical snapshots                                        | Future enhancement: add as-of-date parameter for point-in-time reporting                                        |
