Skip to main content

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:
equa-web/src/modules/agreements/
├── components/   # Agreement list, detail, authorization management
├── services/     # API client for agreements and authorizations
├── store/        # State management for agreements
└── index.tsx
Backend modules: Agreement entities span the 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.
equa-server/modules/captable/      # OperatingAgreement and related join entities
equa-server/modules/persistence/   # Entity definitions

3. Data Model

Entities

EntityDescriptionFile
OperatingAgreementsPoint-in-time snapshot of equity structureequa-server/modules/persistence/src/entity/OperatingAgreements.ts
OperatingAgreementsShareholdingsJoin: operating agreement ↔ shareholdings (composite PK)equa-server/modules/persistence/src/entity/OperatingAgreementsShareholdings.ts
OperatingAgreementsTransactionsView entity: recursive CTE joining operating agreements and hash listsequa-server/modules/persistence/src/entity/OperatingAgreementsTransactions.ts
AuthorizationsBoard-level approvals attached to documentsequa-server/modules/persistence/src/entity/Authorizations.ts

Key Fields — OperatingAgreements

FieldTypeNullableDescription
organizationuuidNoOwning organization
timestampDateNoPoint-in-time this agreement represents
organizationDetailsHashNoSnapshot of org details at this point
plansHashYesSnapshot of equity incentive plans
shareholdingsHashYesSnapshot of all shareholdings
securityTypesSeniorityHashYesSecurity type seniority ordering
securityTypesSharesHashYesShare counts by security type
transactionsHashYesSnapshot of transactions
previousHashYesLink to the prior operating agreement (chain)

Key Fields — OperatingAgreementsShareholdings

FieldTypeNullableDescription
operatingAgreementHashNoPart of composite PK
shareholdingHashNoPart of composite PK

Key Fields — OperatingAgreementsTransactions

This is a ViewEntity backed by a recursive CTE that joins operating_agreements with hash_lists to materialize the full transaction chain for a given agreement.

Key Fields — Authorizations

FieldTypeNullableDescription
organizationuuidNoOwning organization
targetstringNoWhat is being authorized (e.g. plan, transaction)
authorizationDateDateNoDate of board authorization
documentHashYesReference to the authorization document
notetextYesFree-text note
reasonuuidYesReference to the reason / triggering event
documentTypeNamestringYesType label for the attached document
deletedbooleanNoSoft-delete flag

Relationships

Content-Addressed Hashing

All Hash-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 previous chain forms a tamper-evident linked list of every equity-structure change.
  • Deduplication: identical data produces identical hashes, preventing redundant storage.

4. API Endpoints

MethodPathAuthDescription
GET/v1/organizations/:orgId/agreementsSessionList operating agreements
POST/v1/organizations/:orgId/agreementsSessionCreate a new operating agreement snapshot
GET/v1/organizations/:orgId/agreements/:hashSessionGet agreement details
GET/v1/organizations/:orgId/agreements/:hash/shareholdingsSessionList shareholdings in this agreement
GET/v1/organizations/:orgId/agreements/:hash/transactionsSessionList transactions in this agreement
GET/v1/organizations/:orgId/agreements/latestSessionGet the most recent agreement
GET/v1/organizations/:orgId/authorizationsSessionList authorizations
POST/v1/organizations/:orgId/authorizationsSessionCreate a new authorization
GET/v1/organizations/:orgId/authorizations/:idSessionGet authorization details
PUT/v1/organizations/:orgId/authorizations/:idSessionUpdate an authorization
DELETE/v1/organizations/:orgId/authorizations/:idSessionSoft-delete an authorization

5. Frontend Components

ComponentFilePurpose
AgreementsPageequa-web/src/modules/agreements/components/AgreementsPage.tsxList operating agreements chronologically
AgreementDetailequa-web/src/modules/agreements/components/AgreementDetail.tsxView a single agreement snapshot
AgreementDiffequa-web/src/modules/agreements/components/AgreementDiff.tsxCompare two agreement snapshots
AuthorizationsListequa-web/src/modules/agreements/components/AuthorizationsList.tsxList board authorizations
AuthorizationFormequa-web/src/modules/agreements/components/AuthorizationForm.tsxCreate/edit an authorization

Routes

RouteComponentDescription
/organizations/:orgId/agreementsAgreementsPageAgreement listing
/organizations/:orgId/agreements/:hashAgreementDetailSingle agreement detail
/organizations/:orgId/authorizationsAuthorizationsListAuthorization listing

State Management

Agreements state is managed within the agreements 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

RuleDescriptionEnforcement
AGR-001A new operating agreement must reference the current latest agreement as previousBackend
AGR-002Operating agreements are append-only; existing snapshots cannot be modifiedBackend
AGR-003The previous chain must be acyclic (no circular references)Backend
AGR-004Authorization document hash must reference a valid uploaded documentBackend
AGR-005Soft-deleted authorizations are excluded from active queries but retained for auditBackend
AGR-006Only organization admins can create operating agreements or authorizationsBoth
AGR-007Each operating agreement must have a timestamp that is on or after its previous agreement’s timestampBackend

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 previous hash
  • 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

RiskLikelihoodImpactMitigation
Hash collision in content-addressed dataVery LowCriticalUse cryptographic hash function (SHA-256+); collision probability negligible
Broken previous chain (orphaned agreements)LowHighForeign-key-like constraint; validate chain integrity on creation
Recursive CTE performance on long historiesMedMedLimit recursion depth in query; paginate transaction results
Stale snapshot if cap table changes between creation stepsLowMedCapture agreement atomically within a single transaction
Authorization document references invalid hashLowMedValidate document hash exists before persisting authorization

9. Dependencies

DependencyTypeStatus
SPEC 003: Cap TableRequired beforeDRAFT
SPEC 004: ESOPIntegrates withDRAFT
SPEC 007: Documents and DocGenIntegrates withDRAFT
SPEC 012: Team Members and RolesRequired beforeDRAFT