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

# Cap Table

> Shareholdings, security types, share pricing, funding rounds, valuations, transfers, and certificate signatures

# SPEC 003 — Cap Table

| Field    | Value                                                         |
| -------- | ------------------------------------------------------------- |
| Status   | DRAFT                                                         |
| Priority | P0 — Launch-Critical                                          |
| Backend  | `equa-server/modules/captable/`                               |
| API      | `equa-server/modules/api/src/endpoints/captable-endpoints.ts` |
| Frontend | `equa-web/src/modules/captable/`                              |

> **Confluence sources incorporated:** "Allocation Graphs," "Capitalization V1" — see sections 6a and 6b below

***

## 1. Feature Purpose

The cap table is the core product of Equa. It tracks who owns what in an organization — shareholdings, security types, pricing, funding rounds, valuations, and ownership transfers. Every share issuance produces a signed certificate with legends. The cap table powers the fully-diluted ownership view, capital change history, and investor reporting.

***

## 2. Current State (Verified)

### 2.1 Backend

| Component     | Path                                                          |
| ------------- | ------------------------------------------------------------- |
| Module root   | `equa-server/modules/captable/`                               |
| API endpoints | `equa-server/modules/api/src/endpoints/captable-endpoints.ts` |

### 2.2 Frontend

| Component        | Path                                     |
| ---------------- | ---------------------------------------- |
| Cap table module | `equa-web/src/modules/captable/`         |
| Service layer    | `equa-web/src/service/services/captable` |
| Redux state      | `capTableReducer` in `root-reducer.ts`   |

***

## 3. Data Model

### Shareholdings

| Column             | Type    | Constraints                                  |
| ------------------ | ------- | -------------------------------------------- |
| member             | uuid    | FK → Members                                 |
| organization       | uuid    | FK → Organizations                           |
| shares             | numeric | Precision-safe share count                   |
| securityType       | hash    | FK → SecurityTypes (content-addressed)       |
| issueDate          | date    |                                              |
| serialNumber       | int     | Certificate serial within org                |
| shareholderName    | varchar | Name as printed on certificate               |
| legend             | hash    | FK → Legends (content-addressed)             |
| exercised          | boolean | Whether options/warrants have been exercised |
| legacyShareholding | boolean | Migrated from legacy system                  |

### SecurityTypes

| Column           | Type     | Constraints                                       |
| ---------------- | -------- | ------------------------------------------------- |
| organization     | uuid     | FK → Organizations                                |
| shareClass       | varchar  | e.g. "Common", "Series A Preferred"               |
| shareType        | smallint | Enum (common, preferred, options, warrants, etc.) |
| certifiedShares  | boolean  | Whether share certificates are issued             |
| votingShares     | boolean  | Carries voting rights                             |
| price            | numeric  | Default price per share                           |
| name             | varchar  | Display name                                      |
| sharePricing     | hash     | FK → SharePricingTable (content-addressed)        |
| fractionalShares | boolean  | Allows fractional ownership                       |

### SecurityDetails

Related metadata for security types (structure follows SecurityTypes context).

### SecurityTypeSeniorityTable

Tracks liquidation preference ordering among security types within an organization.

### SecurityTypeSharesTable

Aggregated share counts per security type (authorized, outstanding, reserved).

### SharePricingTable

| Column             | Type    | Constraints                |
| ------------------ | ------- | -------------------------- |
| pricePerShare      | numeric |                            |
| parValue           | numeric |                            |
| originalIssuePrice | numeric |                            |
| conversionPrice    | numeric | For convertible securities |
| conversionRate     | numeric | Conversion ratio           |

### Holdings

| Column       | Type    | Constraints                            |
| ------------ | ------- | -------------------------------------- |
| entity       | uuid    | Organization or fund entity            |
| owner        | uuid    | Member or entity that owns the holding |
| value        | numeric | Share count or unit value              |
| holdingType  | varchar | Type classification                    |
| name         | varchar | Display name                           |
| class        | varchar | Share class label                      |
| issueDate    | date    |                                        |
| pricePerUnit | numeric |                                        |
| outstanding  | numeric | Currently outstanding                  |
| authorized   | numeric | Total authorized                       |
| fullyDiluted | numeric | Fully-diluted count                    |

### CapitalChanges

| Column       | Type      | Constraints                                 |
| ------------ | --------- | ------------------------------------------- |
| mod          | numeric   | Change amount (positive or negative)        |
| timestamp    | timestamp | When the change occurred                    |
| type         | uuid      | FK → SecurityTypes or change-type reference |
| organization | uuid      | FK → Organizations                          |

### FundingRounds

| Column         | Type    | Constraints               |
| -------------- | ------- | ------------------------- |
| id             | uuid    | PK                        |
| organization   | uuid    | FK → Organizations        |
| number         | int     | Round sequence number     |
| endDate        | date    |                           |
| totalCommon    | numeric | Common shares in round    |
| totalPreferred | numeric | Preferred shares in round |
| name           | varchar | e.g. "Seed", "Series A"   |

### Valuations

| Column    | Type    | Constraints            |
| --------- | ------- | ---------------------- |
| entity    | uuid    | FK → Organizations     |
| issueDate | date    | Valuation date         |
| value     | numeric | Valuation amount       |
| units     | varchar | Currency or unit label |

### Transfers

| Column  | Type | Constraints                                    |
| ------- | ---- | ---------------------------------------------- |
| inputs  | hash | Content-addressed reference to source holdings |
| outputs | hash | Content-addressed reference to TransferOutputs |

### TransferOutputs

| Column  | Type    | Constraints                         |
| ------- | ------- | ----------------------------------- |
| holding | hash    | Content-addressed holding reference |
| owner   | uuid    | FK → new owner (Member or entity)   |
| value   | numeric | Transferred amount                  |

### Legends

| Column  | Type | Constraints                                  |
| ------- | ---- | -------------------------------------------- |
| content | text | Full legend text (content-addressed by hash) |

### LegendMetas

| Column       | Type    | Constraints                       |
| ------------ | ------- | --------------------------------- |
| legend       | hash    | FK → Legends                      |
| organization | uuid    | FK → Organizations                |
| name         | varchar | Legend display name               |
| author       | uuid    | FK → Users who created the legend |

### Signatures

| Column       | Type    | Constraints                 |
| ------------ | ------- | --------------------------- |
| id           | uuid    | PK                          |
| shareholding | uuid    | FK → Shareholdings          |
| signatory    | uuid    | FK → Members                |
| name         | varchar | Signatory name as displayed |
| title        | varchar | Signatory title             |

***

## 4. API Endpoints

| Method | Path                                             | Auth | Description                       |
| ------ | ------------------------------------------------ | ---- | --------------------------------- |
| GET    | `/api/v1/organizations/:id/captable`             | Yes  | Full cap table for organization   |
| GET    | `/api/v1/organizations/:id/shareholdings`        | Yes  | List all shareholdings            |
| POST   | `/api/v1/organizations/:id/shareholdings`        | Yes  | Issue new shares                  |
| PUT    | `/api/v1/organizations/:id/shareholdings/:shId`  | Yes  | Update a shareholding             |
| DELETE | `/api/v1/organizations/:id/shareholdings/:shId`  | Yes  | Cancel / void a shareholding      |
| GET    | `/api/v1/organizations/:id/security-types`       | Yes  | List security types               |
| POST   | `/api/v1/organizations/:id/security-types`       | Yes  | Create a security type            |
| PUT    | `/api/v1/organizations/:id/security-types/:stId` | Yes  | Update a security type            |
| GET    | `/api/v1/organizations/:id/funding-rounds`       | Yes  | List funding rounds               |
| POST   | `/api/v1/organizations/:id/funding-rounds`       | Yes  | Create a funding round            |
| GET    | `/api/v1/organizations/:id/valuations`           | Yes  | List valuations                   |
| POST   | `/api/v1/organizations/:id/valuations`           | Yes  | Record a valuation                |
| POST   | `/api/v1/organizations/:id/transfers`            | Yes  | Execute a share transfer          |
| GET    | `/api/v1/organizations/:id/capital-changes`      | Yes  | Capital change history            |
| GET    | `/api/v1/organizations/:id/legends`              | Yes  | List legends                      |
| POST   | `/api/v1/organizations/:id/legends`              | Yes  | Create a legend                   |
| GET    | `/api/v1/organizations/:id/signatures`           | Yes  | List certificate signatures       |
| POST   | `/api/v1/organizations/:id/signatures`           | Yes  | Add a signature to a shareholding |

***

## 5. Frontend Components

| Component          | Path                                     | Description                                             |
| ------------------ | ---------------------------------------- | ------------------------------------------------------- |
| Cap table module   | `equa-web/src/modules/captable/`         | Cap table management, shareholding list, issuance forms |
| Shareholdings view | `equa-web/src/modules/captable/`         | Individual shareholding detail and certificate preview  |
| Certificates       | `equa-web/src/modules/captable/`         | Certificate generation with legends and signatures      |
| Service layer      | `equa-web/src/service/services/captable` | API client for cap table operations                     |
| Redux reducer      | `capTableReducer` in `root-reducer.ts`   | Client-side state for cap table data                    |

***

## 6. Business Rules

1. **Numeric precision** — Shares, prices, and valuations use `numeric` type (arbitrary precision) to avoid floating-point errors in financial calculations.
2. **Content-addressed immutability** — SecurityTypes, Legends, SharePricing, and Transfers reference content by hash, ensuring historical records cannot be silently altered.
3. **Serial numbers** — Each shareholding within an organization receives a sequential `serialNumber` for certificate identification.
4. **Fractional shares** — Allowed only when `SecurityTypes.fractionalShares = true` for the relevant security type.
5. **Transfer integrity** — Transfers use input/output hashes; the sum of output values must equal the input holding value (no shares created or destroyed).
6. **Exercised flag** — Options and warrants track `exercised = true` once converted, preventing double exercise.
7. **Seniority ordering** — `SecurityTypeSeniorityTable` determines liquidation preference order among security types.
8. **Fully-diluted calculation** — Holdings track `outstanding`, `authorized`, and `fullyDiluted` separately to support both basic and diluted ownership views.
9. **Legends on certificates** — Every shareholding references a legend hash; legends are immutable once assigned to issued certificates.
10. **Signatures required** — Certificates require at least one Signature record linking a signatory member with name and title.
11. **Legacy flag** — `legacyShareholding = true` marks shareholdings imported from the previous system for migration tracking.

***

## 6a. Allocation Graph Model (from Confluence KnowledgeBase)

> **Source:** Confluence KnowledgeBase — [Allocation Graphs](https://equa.atlassian.net/wiki/spaces/KNOWLEDGEB/pages/10616907/Allocation+Graphs) (by Christopher Johnson)

An entity can be divided into units, which are grouped into pools. Pools can be subdivided into child pools, forming a hierarchy called an **allocation graph**. An allocation graph is itself an entity.

**Node properties:**

* `value` — the amount of units allocated to the node
* `children` — zero or more child nodes (sum of children's values must not exceed parent's value)
* `parent` — every node except the root must have exactly one parent

**Partition types** — the units of a pool divide into:

* **Outstanding** — issued and held by shareholders
* **External Reserved** — allocated for external parties (investors, advisors)
* **Treasury (Internal Reserved)** — held internally by the organization

## 6b. Capitalization V1 User Stories (from Confluence KnowledgeBase)

> **Source:** Confluence KnowledgeBase — [Capitalization V1](https://equa.atlassian.net/wiki/spaces/KNOWLEDGEB/pages/375881740/Capitalization+V1) (by Christopher Johnson)

**User stories (outstanding holdings only):**

* Transfer shares without affecting capital contributions of the source holding
* Edit capital contributions of an active holding
* Cancel a holding and preserve its capital contributions
* Cancel a holding and its capital contributions
* Edit capital contributions of a cancelled holding
* Edit capital contribution of a holding that was transferred (effectively cancelled)

**Key requirements:**

* When a holding is cancelled or transferred, capital contributions remain active by default
* To cancel both a holding and its contributions: set contributions to zero, then cancel the holding
* Users with cap table edit permission can edit cancelled holdings (known UI bug: "Resource Not Found" error)
* Capital contribution fields in the Transfer form are deprecated and should not be used

***

## 7. Acceptance Criteria

* [ ] Organization owner can create security types with class, pricing, voting, and fractional share settings
* [ ] Shares can be issued to members with correct serial number auto-increment
* [ ] Share pricing (price per share, par value, original issue price, conversion terms) is stored accurately
* [ ] Shareholdings display on the cap table with correct ownership percentages
* [ ] Fully-diluted view includes outstanding, authorized, and fully-diluted counts
* [ ] Share transfers move ownership atomically (inputs → outputs) with value conservation
* [ ] Options/warrants can be marked as exercised; double exercise is prevented
* [ ] Funding rounds track common and preferred totals with round name and end date
* [ ] Valuations are recorded per entity with date, value, and unit
* [ ] Capital changes history logs every issuance, transfer, and cancellation
* [ ] Legends are immutable and content-addressed
* [ ] Certificates include legend text and at least one signature
* [ ] Security type seniority ordering is configurable
* [ ] Fractional shares are rejected when `fractionalShares = false`
* [ ] Redux state stays in sync with server after cap table mutations

***

## 8. Risks

| Risk                                                 | Impact                              | Mitigation                                                                |
| ---------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------- |
| Numeric precision loss in frontend JavaScript        | Incorrect ownership percentages     | Use string-based numeric transport; parse with decimal library on client  |
| Transfer value mismatch (inputs ≠ outputs)           | Phantom shares created or destroyed | Server-side validation: sum(outputs.value) must equal input holding value |
| Concurrent issuance creates duplicate serial numbers | Certificate numbering conflict      | Use database sequence or serialized transaction for serial assignment     |
| Content-addressed hash collision                     | Wrong legend or pricing served      | SHA-256 makes collision negligible; add unique constraint on hash         |
| Legacy shareholding flag not consistently checked    | Incorrect display for migrated data | Centralize legacy handling in service layer                               |
| Large cap tables degrade query performance           | Slow page loads                     | Paginate shareholdings; index on (organization, securityType)             |
| Missing signature on issued certificate              | Legally incomplete document         | Enforce minimum one signature at issuance time via validation             |
