SPEC 005: Agreements
Status: DRAFT Priority: P0 Created: 2026-02-21 Approved: pending Repo(s): equa-web, equa-server
1. Feature Purpose
The Agreements module manages an organization’s governing documents — primarily operating agreements and board authorizations. An operating agreement represents a point-in-time snapshot of the organization’s equity structure, capturing shareholdings, security types, plans, and transactions as immutable, content-addressed records. Authorizations track board-level approvals attached to specific documents. Together, these provide a legally auditable chain of the company’s equity history.2. Current State (Verified)
Frontend module:organization and captable server modules. Operating agreements reference cap-table entities (shareholdings, securities, plans, transactions) via content-addressed hashes. Authorizations are managed alongside organization-level data.
3. Data Model
Entities
| Entity | Description | File |
|---|---|---|
| OperatingAgreements | Point-in-time snapshot of equity structure | equa-server/modules/persistence/src/entity/OperatingAgreements.ts |
| OperatingAgreementsShareholdings | Join: operating agreement ↔ shareholdings (composite PK) | equa-server/modules/persistence/src/entity/OperatingAgreementsShareholdings.ts |
| OperatingAgreementsTransactions | View entity: recursive CTE joining operating agreements and hash lists | equa-server/modules/persistence/src/entity/OperatingAgreementsTransactions.ts |
| Authorizations | Board-level approvals attached to documents | equa-server/modules/persistence/src/entity/Authorizations.ts |
Key Fields — OperatingAgreements
| Field | Type | Nullable | Description |
|---|---|---|---|
organization | uuid | No | Owning organization |
timestamp | Date | No | Point-in-time this agreement represents |
organizationDetails | Hash | No | Snapshot of org details at this point |
plans | Hash | Yes | Snapshot of equity incentive plans |
shareholdings | Hash | Yes | Snapshot of all shareholdings |
securityTypesSeniority | Hash | Yes | Security type seniority ordering |
securityTypesShares | Hash | Yes | Share counts by security type |
transactions | Hash | Yes | Snapshot of transactions |
previous | Hash | Yes | Link to the prior operating agreement (chain) |
Key Fields — OperatingAgreementsShareholdings
| Field | Type | Nullable | Description |
|---|---|---|---|
operatingAgreement | Hash | No | Part of composite PK |
shareholding | Hash | No | Part of composite PK |
Key Fields — OperatingAgreementsTransactions
This is a ViewEntity backed by a recursive CTE that joinsoperating_agreements with hash_lists to materialize the full transaction chain for a given agreement.
Key Fields — Authorizations
| Field | Type | Nullable | Description |
|---|---|---|---|
organization | uuid | No | Owning organization |
target | string | No | What is being authorized (e.g. plan, transaction) |
authorizationDate | Date | No | Date of board authorization |
document | Hash | Yes | Reference to the authorization document |
note | text | Yes | Free-text note |
reason | uuid | Yes | Reference to the reason / triggering event |
documentTypeName | string | Yes | Type label for the attached document |
deleted | boolean | No | Soft-delete flag |
Relationships
Content-Addressed Hashing
AllHash-typed fields are content-addressed identifiers. This guarantees:
- Immutability: once an agreement snapshot is created, its referenced data cannot be altered without producing a different hash.
- Auditability: the
previouschain forms a tamper-evident linked list of every equity-structure change. - Deduplication: identical data produces identical hashes, preventing redundant storage.
4. API Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /v1/organizations/:orgId/agreements | Session | List operating agreements |
| POST | /v1/organizations/:orgId/agreements | Session | Create a new operating agreement snapshot |
| GET | /v1/organizations/:orgId/agreements/:hash | Session | Get agreement details |
| GET | /v1/organizations/:orgId/agreements/:hash/shareholdings | Session | List shareholdings in this agreement |
| GET | /v1/organizations/:orgId/agreements/:hash/transactions | Session | List transactions in this agreement |
| GET | /v1/organizations/:orgId/agreements/latest | Session | Get the most recent agreement |
| GET | /v1/organizations/:orgId/authorizations | Session | List authorizations |
| POST | /v1/organizations/:orgId/authorizations | Session | Create a new authorization |
| GET | /v1/organizations/:orgId/authorizations/:id | Session | Get authorization details |
| PUT | /v1/organizations/:orgId/authorizations/:id | Session | Update an authorization |
| DELETE | /v1/organizations/:orgId/authorizations/:id | Session | Soft-delete an authorization |
5. Frontend Components
| Component | File | Purpose |
|---|---|---|
| AgreementsPage | equa-web/src/modules/agreements/components/AgreementsPage.tsx | List operating agreements chronologically |
| AgreementDetail | equa-web/src/modules/agreements/components/AgreementDetail.tsx | View a single agreement snapshot |
| AgreementDiff | equa-web/src/modules/agreements/components/AgreementDiff.tsx | Compare two agreement snapshots |
| AuthorizationsList | equa-web/src/modules/agreements/components/AuthorizationsList.tsx | List board authorizations |
| AuthorizationForm | equa-web/src/modules/agreements/components/AuthorizationForm.tsx | Create/edit an authorization |
Routes
| Route | Component | Description |
|---|---|---|
/organizations/:orgId/agreements | AgreementsPage | Agreement listing |
/organizations/:orgId/agreements/:hash | AgreementDetail | Single agreement detail |
/organizations/:orgId/authorizations | AuthorizationsList | Authorization listing |
State Management
Agreements state is managed within theagreements module store. The operating-agreement chain is loaded lazily — the latest agreement is fetched first, with prior snapshots loaded on demand for diff views.
6. Business Rules and Validation
| Rule | Description | Enforcement |
|---|---|---|
| AGR-001 | A new operating agreement must reference the current latest agreement as previous | Backend |
| AGR-002 | Operating agreements are append-only; existing snapshots cannot be modified | Backend |
| AGR-003 | The previous chain must be acyclic (no circular references) | Backend |
| AGR-004 | Authorization document hash must reference a valid uploaded document | Backend |
| AGR-005 | Soft-deleted authorizations are excluded from active queries but retained for audit | Backend |
| AGR-006 | Only organization admins can create operating agreements or authorizations | Both |
| AGR-007 | Each operating agreement must have a timestamp that is on or after its previous agreement’s timestamp | Backend |
7. Acceptance Criteria
- AC-1: Admin can create a new operating agreement that snapshots current shareholdings, plans, securities, and transactions
- AC-2: New agreement automatically links to the previous agreement via
previoushash - AC-3: Agreement detail view displays all captured shareholdings and transactions
- AC-4: User can compare two agreement snapshots to see equity structure changes
- AC-5: Admin can create a board authorization with date, document, and notes
- AC-6: Soft-deleting an authorization hides it from active views but preserves audit trail
- AC-7: Recursive CTE correctly materializes the full transaction list for OperatingAgreementsTransactions
- AC-8: Content-addressed hashes are correctly computed and verified on read
- AC-9: Agreement chain is displayed chronologically with linked-list navigation
8. Risks and Edge Cases
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Hash collision in content-addressed data | Very Low | Critical | Use cryptographic hash function (SHA-256+); collision probability negligible |
Broken previous chain (orphaned agreements) | Low | High | Foreign-key-like constraint; validate chain integrity on creation |
| Recursive CTE performance on long histories | Med | Med | Limit recursion depth in query; paginate transaction results |
| Stale snapshot if cap table changes between creation steps | Low | Med | Capture agreement atomically within a single transaction |
| Authorization document references invalid hash | Low | Med | Validate document hash exists before persisting authorization |
9. Dependencies
| Dependency | Type | Status |
|---|---|---|
| SPEC 003: Cap Table | Required before | DRAFT |
| SPEC 004: ESOP | Integrates with | DRAFT |
| SPEC 007: Documents and DocGen | Integrates with | DRAFT |
| SPEC 012: Team Members and Roles | Required before | DRAFT |