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

# Documents and Document Generation

> File storage, data room, governing documents, certificate generation, operating agreement templates, and data room access control

# SPEC 007 — Documents and Document Generation

| Field    | Value                                                                                                                |
| -------- | -------------------------------------------------------------------------------------------------------------------- |
| Status   | DRAFT                                                                                                                |
| Priority | P1 — Core Product                                                                                                    |
| Backend  | `equa-server/modules/data-room/`, `equa-server/modules/doc-gen/`, `equa-server/modules/file-storage/`                |
| API      | `equa-server/modules/api/src/endpoints/data-room-endpoints.ts`, `organization-endpoints.ts`, `captable-endpoints.ts` |
| Frontend | `equa-web/src/modules/documents/`, `equa-web/src/modules/agreements/`                                                |

***

## 1. Feature Purpose

Documents and DocGen provides the file management infrastructure for the entire Equa platform. It covers three areas:

1. **Data Room** — General-purpose virtual file storage with folders, uploads, renaming, and deletion
2. **Governing Documents** — Categorized legal document repository (formation, operating, shareholder, board, employment, investor, compliance)
3. **Document Generation** — Automated creation of stock certificates (SVG templates rendered to PDF) and operating agreements (Handlebars DOCX templates)

All files are stored on AWS S3 with content-addressed hashing. The system supports DOCX-to-PDF server-side conversion for inline viewing.

***

## 2. Current State (Verified)

### 2.1 Backend

| Component                      | Path                                                                                      |
| ------------------------------ | ----------------------------------------------------------------------------------------- |
| Data room persistence (read)   | `equa-server/modules/persistence/src/data-room/reading.ts`                                |
| Data room persistence (write)  | `equa-server/modules/persistence/src/data-room/writing.ts`                                |
| File storage (S3)              | `equa-server/modules/file-storage/src/s3.ts`                                              |
| Upload middleware              | `equa-server/modules/file-storage/src/uploading.ts`                                       |
| Doc-gen module                 | `equa-server/modules/doc-gen/`                                                            |
| Certificate templates          | `equa-server/modules/doc-gen/res/templates/certificate-front.svg`, `certificate-back.svg` |
| API doc-gen wrappers           | `equa-server/modules/api/src/doc-gen/generation.ts`                                       |
| Data room endpoints            | `equa-server/modules/api/src/endpoints/data-room-endpoints.ts`                            |
| Organization endpoints (files) | `equa-server/modules/api/src/endpoints/organization-endpoints.ts`                         |
| Cap table endpoints (certs)    | `equa-server/modules/api/src/endpoints/captable-endpoints.ts`                             |
| Authorization persistence      | `equa-server/modules/persistence/src/organizations/reading.ts`, `writing.ts`              |

### 2.2 Frontend

| Component                    | Path                                                               |
| ---------------------------- | ------------------------------------------------------------------ |
| Data room module             | `equa-web/src/modules/documents/`                                  |
| Agreements module            | `equa-web/src/modules/agreements/`                                 |
| Web client (upload/download) | `equa-web/src/service/services/web-client.ts`                      |
| Shared documents component   | `equa-web/src/shared/components/documents-and-notes.tsx`           |
| ESOP plan documents          | `equa-web/src/modules/esop/pages/all-plan-documents.tsx`           |
| Cap table doc/notes page     | `equa-web/src/modules/captable/pages/documents-and-notes-page.tsx` |

***

## 3. Data Model

### 3.1 DirectoryItems

Virtual filesystem entries (files and folders) organized by path.

| Column       | Type     | Constraints          | Description                                 |
| ------------ | -------- | -------------------- | ------------------------------------------- |
| organization | uuid     | PK (composite)       | Owning organization                         |
| parentPath   | varchar  | PK (composite)       | Parent folder path (e.g., `/` or `/legal/`) |
| name         | varchar  | PK (composite)       | File or folder name                         |
| file         | uuid     | nullable, FK → Files | Null for folders, set for files             |
| type         | smallint | unsigned             | 2 = folder, other = file                    |
| size         | number   |                      | File size in bytes (0 for folders)          |

Extends: `CreatedModifiedDeleted`

Source: `schema.ts` lines 564–582

### 3.2 Files

Content-addressed file records stored on S3.

| Column      | Type    | Constraints | Description                          |
| ----------- | ------- | ----------- | ------------------------------------ |
| id          | uuid    | PK          | File identifier                      |
| hash        | Hash    | nullable    | Content hash for deduplication       |
| filename    | varchar |             | Original filename                    |
| url         | varchar |             | S3 URL or path                       |
| extension   | varchar |             | File extension (e.g., `pdf`, `docx`) |
| contentType | varchar |             | MIME type                            |
| size        | number  |             | File size in bytes                   |
| owner       | uuid    | FK → Users  | Uploading user                       |

Extends: `CreatedModified`

Source: `schema.ts` lines 585–609

### 3.3 Authorizations

Document authorizations linking approval records to organizations.

| Column            | Type    | Constraints           | Description                             |
| ----------------- | ------- | --------------------- | --------------------------------------- |
| (hash)            | Hash    | PK (from HashedTable) | Content-addressed identifier            |
| authorizationDate | date    | nullable              | Date of authorization                   |
| document          | Hash    | nullable              | Reference to authorized document        |
| note              | text    | nullable              | Free-text note                          |
| organization      | uuid    | FK → Organizations    | Owning organization                     |
| reason            | uuid    | nullable              | Reason reference                        |
| target            | varchar |                       | Target entity or path                   |
| documentTypeName  | varchar | nullable              | Type label (e.g., "Issuance Agreement") |
| deleted           | boolean | default: false        | Soft-delete flag                        |

Extends: `HashedTable`

Source: `schema.ts` lines 1378–1402

### 3.4 OrganizationTemplates

Stored document templates (certificate legends, operating agreement content).

| Column       | Type    | Constraints    | Description                     |
| ------------ | ------- | -------------- | ------------------------------- |
| organization | uuid    | PK (composite) | Owning organization             |
| type         | varchar | PK (composite) | Template type identifier        |
| content      | Hash    |                | Content-addressed template body |

Extends: `CreatedModifiedDeleted`

Source: `schema.ts` lines 1405–1414

### 3.5 DataRoomsMembers (Access Control)

<Note>
  This section covers the data model previously planned as Spec 008 (Data Rooms). The entity and persistence functions exist, but **no REST API endpoints or frontend UI** are implemented for managing data room membership. The legacy Microsoft path restriction (`processRestrictedPath` in `microsoft/src/reading.ts`) is deprecated. Modern data room access control needs a separate specification.
</Note>

Member-level access control for named data rooms.

| Column       | Type    | Constraints                      | Description                           |
| ------------ | ------- | -------------------------------- | ------------------------------------- |
| dataRoomName | varchar | PK (composite)                   | Named data room (maps to folder path) |
| member       | uuid    | PK (composite), FK → Members     | Authorized member                     |
| permission   | uuid    | PK (composite), FK → Permissions | Granted permission                    |

Source: `schema.ts` lines 164–174

**Persistence functions (exist, not exposed via REST):**

* `getDataRoomsPermissionsForMember(db, organization, member)` — Query by org + member (`common/reading.ts` line 576)
* `getDataRoomsPermissionsForOrganizationAnUser(db, organization, user)` — Query by org + user, joins through Members (`common/reading.ts` line 580)
* `insertDataRoomsMembers(db, record)` — Insert single record (`common/writing.ts` line 319)

**Legacy path restriction (deprecated):**
`processRestrictedPath` in `microsoft/src/reading.ts` line 51 restricts folder paths for non-admin users based on their `dataRoomName` entries. Admins bypass. This was built for Microsoft Graph/SharePoint storage and is not used with the current native file storage.

**Gap:** No endpoints exist for granting/revoking data room access. No frontend UI for data room member management. A future spec should define modern access control for Google Drive integration or native storage.

### 3.6 File Storage Backend

Files are stored on **AWS S3** (`file-storage/src/s3.ts`):

* Upload: `uploadS3(config, hash, stream)` — stores with hash as S3 object name
* Download: `downloadS3(config, hash)` — retrieves by hash
* Configuration: `AwsFileStorageConfig` with `accessKeyId`, `secretAccessKey`, `bucket`, `cacheBucket`, `region`, `tempPath`

### Relationships

```mermaid theme={null}
erDiagram
    Organizations ||--o{ DirectoryItems : "owns"
    DirectoryItems }o--o| Files : "points to"
    Files }o--|| Users : "uploaded by"
    Organizations ||--o{ Authorizations : "has"
    Organizations ||--o{ OrganizationTemplates : "has"
    Organizations ||--o{ DataRoomsMembers : "controls access"
    Members ||--o{ DataRoomsMembers : "granted access"
    Permissions ||--o{ DataRoomsMembers : "type of access"
```

***

## 4. API Endpoints

### Data Room Endpoints

| Method | Path                                                           | Auth Guard          | Description                                                   |
| ------ | -------------------------------------------------------------- | ------------------- | ------------------------------------------------------------- |
| GET    | `/organization/:organization/document`                         | canViewOrganization | List documents at path (query: `?path=/`)                     |
| GET    | `/organization/:organization/document/:document/content`       | canViewDocuments    | Download file (attachment disposition)                        |
| GET    | `/organization/:organization/document/:document/content/:name` | canViewDocuments    | View file inline (supports `?format=pdf` for DOCX conversion) |
| POST   | `/organization/:organization/document`                         | canEditDocuments    | Upload files (multipart, max 10 MB default)                   |
| POST   | `/organization/:organization/folder`                           | canEditDocuments    | Create folder                                                 |
| POST   | `/organization/:organization/document/:document/move`          | canEditDocuments    | Rename or move document/folder                                |
| DELETE | `/organization/:organization/document/:document`               | canEditDocuments    | Delete document (query: `?fullPath=...`)                      |

Source: `data-room-endpoints.ts` lines 40–117

Upload middleware: `uploadMiddlewareUsingMemory` with `maxSizeMegabytes: parseInt(process.env.DATA_ROOM_UPLOAD_SIZE_LIMIT_MB || '10')`

### Organization File Endpoints

| Method | Path                                                       | Auth Guard       | Description                                  |
| ------ | ---------------------------------------------------------- | ---------------- | -------------------------------------------- |
| POST   | `/organization/:organization/file`                         | canEditDocuments | Upload organization file (max 21 MB default) |
| GET    | `/file/:file/content`                                      | —                | Download file by ID                          |
| GET    | `/file/:file/content/:name`                                | —                | View file inline by ID                       |
| GET    | `/authorization`                                           | —                | Get authorizations                           |
| POST   | `/organization/:organization/authorization`                | canEditDocuments | Create authorization                         |
| DELETE | `/organization/:organization/authorization/:authorization` | canEditDocuments | Delete authorization                         |

Source: `organization-endpoints.ts` lines 208–251

### Certificate Generation Endpoints

| Method | Path                                      | Auth Guard      | Description                           |
| ------ | ----------------------------------------- | --------------- | ------------------------------------- |
| GET    | `/shareholding/:holding/certificate`      | canViewCapTable | Generate shareholding certificate PDF |
| GET    | `/legend/:legend/certificate`             | canViewCapTable | Generate legend certificate PDF       |
| GET    | `/shareholding/:holding/certificate/copy` | canViewCapTable | Generate certificate copy PDF         |

Source: `captable-endpoints.ts` lines 207–222

***

## 5. Frontend Components

### Data Room

| Component       | File                                        | Purpose                                                         |
| --------------- | ------------------------------------------- | --------------------------------------------------------------- |
| DataRoomPage    | `documents/documents.tsx`                   | Main data room with folder navigation, upload dropzone, modals  |
| DocumentSection | `documents/components/document-section.tsx` | File/folder table with actions (view, rename, delete)           |
| DocumentButtons | `documents/components/document-buttons.tsx` | Upload controls (file, folder, link)                            |
| Modals          | `documents/components/modals.tsx`           | Delete confirmation, rename, new folder, add link, introduction |

**DataRoomPage behavior:**

* Dropzone supports file and folder uploads with progress tracking
* Link creation generates `.url` files (Windows Internet Shortcut format)
* Permission-gated: checks `canEditDocument` for write operations
* Introduction modal shown on first visit to empty data room
* Supports legacy Microsoft Graph paths via `legacyDataRoom` org flag

### Governing Documents

| Component       | File                                         | Purpose                                                 |
| --------------- | -------------------------------------------- | ------------------------------------------------------- |
| AgreementsPage  | `agreements/agreements-page.tsx`             | Category-filtered document list with upload/view/delete |
| AgreementsTable | `agreements/components/agreements-table.tsx` | Document table within a category                        |

**Agreement Categories** (8 total, from `agreements/utils.ts`):

| Category    | Storage Path            | Description                       |
| ----------- | ----------------------- | --------------------------------- |
| all         | `governing`             | Show all governing documents      |
| formation   | `governing/formation`   | Articles of incorporation, bylaws |
| operating   | `governing/operating`   | Operating agreements              |
| shareholder | `governing/shareholder` | Shareholder agreements            |
| board       | `governing/board`       | Board resolutions, minutes        |
| employment  | `governing/employment`  | Employment agreements             |
| investor    | `governing/investor`    | Investor rights, ROFR             |
| compliance  | `governing/compliance`  | Regulatory filings                |

### Document Generation

The `doc-gen` module generates:

1. **Stock certificates** — Front and back pages rendered from SVG templates (`certificate-front.svg`, `certificate-back.svg`) using `pdf-lib` for PDF output. Populated with shareholding data (holder name, share count, serial number, legend text, signatures).

2. **Legend certificates** — Standalone legend document generated from legend content.

3. **Operating agreements** — DOCX documents generated from Handlebars templates via `modules/api/src/doc-gen/generation.ts`. Templates stored in `OrganizationTemplates` entity.

### Shared Components

| Component         | File                                        | Purpose                                                                                                                          |
| ----------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| DocumentsAndNotes | `shared/components/documents-and-notes.tsx` | Reusable form section for document uploads with metadata (type name, approval date, notes). Uses `FieldArray` for multiple docs. |

### Routes

| Route                                                       | Component                 |
| ----------------------------------------------------------- | ------------------------- |
| `/organization/:organization/dataroom`                      | DataRoomPage              |
| `/organization/:organization/documents/governing`           | AgreementsPage            |
| `/organization/:organization/documents/governing/:category` | AgreementsPage (filtered) |
| `${captableCertificatePath}/documentsAndNotes`              | DocumentsAndNotesPage     |
| `${planPath}/documents`                                     | AllPlanDocuments          |

***

## 6. Business Rules and Validation

| Rule                            | Description                                                                                                                | Enforcement                               |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| Composite path uniqueness       | No two items can have the same (organization, parentPath, name)                                                            | Database PK constraint                    |
| Upload size limits              | Data room: 10 MB (configurable via `DATA_ROOM_UPLOAD_SIZE_LIMIT_MB`); General: 21 MB (via `DOCUMENT_UPLOAD_SIZE_LIMIT_MB`) | Server-side middleware                    |
| File type validation            | Currently **not enforced** — validation code exists but is commented out in `file-storage/src/validation.ts` line 48       | None (gap)                                |
| Content-addressed deduplication | Files with identical content share the same S3 object (hash-based naming)                                                  | S3 upload uses `formatS3ObjectName(hash)` |
| DOCX-to-PDF conversion          | Inline viewing of DOCX files triggers server-side conversion via `?format=pdf` query parameter                             | Backend conversion on request             |
| Permission gating               | Data room operations require `canViewDocuments` (read) or `canEditDocuments` (write)                                       | API endpoint guards                       |
| Soft delete on authorizations   | Authorizations use `deleted: boolean` flag rather than hard delete                                                         | Application-level check                   |
| Folder type marker              | DirectoryItems with `type = 2` are folders; others are files                                                               | Application convention                    |
| Legacy data room flag           | Organizations with `legacyDataRoom = true` use Microsoft Graph paths; newer orgs use native S3 storage                     | Frontend path handling                    |

***

## 7. Acceptance Criteria

* [ ] Users with `editDocuments` permission can upload files to the data room (up to configured size limit)
* [ ] Folder creation works with nested paths (e.g., `/legal/contracts/`)
* [ ] Files can be renamed and moved between folders
* [ ] File deletion removes the DirectoryItem record (file content retained in S3 via hash)
* [ ] DOCX files can be viewed inline as PDF via the `?format=pdf` parameter
* [ ] Governing documents page filters correctly by all 8 categories
* [ ] Each category maps to the correct `governing/[category]` storage path
* [ ] Stock certificate generation produces a PDF with front/back pages containing holder info, legend, and signatures
* [ ] Authorizations can be created and deleted, with soft-delete flag
* [ ] Upload progress is displayed in the frontend during file uploads
* [ ] Link creation generates a valid `.url` file in the data room
* [ ] Introduction modal appears on first visit to an empty data room
* [ ] `canViewDocuments` and `canEditDocuments` guards correctly gate all endpoints
* [ ] DataRoomsMembers entity stores access control records (no REST API or UI — documented gap)

***

## 8. Risks and Edge Cases

| Risk                                        | Impact                                                           | Mitigation                                                            |
| ------------------------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------- |
| No file type validation                     | Malicious files could be uploaded                                | Re-enable validation in `file-storage/src/validation.ts`              |
| Upload size limit mismatch (10 MB vs 21 MB) | User confusion about different limits for data room vs org files | Unify limits or display the applicable limit in the UI                |
| S3 credential exposure                      | File storage compromise                                          | Credentials stored in environment variables, not in code              |
| DOCX-to-PDF conversion failure              | Unsupported DOCX features may produce corrupt PDF                | Fallback to download link when conversion fails                       |
| Hash collision (content-addressed)          | Wrong file served                                                | SHA-256 makes collision negligible; add unique constraint on hash     |
| Legacy Microsoft Graph paths                | Broken file access for old organizations                         | Migration path needed; `legacyDataRoom` flag identifies affected orgs |
| DataRoomsMembers has no API/UI              | Cannot manage data room access via the product                   | Future spec needed for modern access control                          |
| Concurrent uploads to same path             | Naming conflict for duplicate filenames                          | Server checks for existing names; appends suffix or rejects           |

***

## 9. Dependencies

| Dependency                               | Type            | Status      |
| ---------------------------------------- | --------------- | ----------- |
| 001-Authentication (user sessions)       | Required before | DRAFT       |
| 002-Organization Management              | Required before | DRAFT       |
| 012-Team Members and Roles (permissions) | Required before | DRAFT       |
| 003-Cap Table (certificate generation)   | Integrates with | DRAFT       |
| 023-File Storage (S3 infrastructure)     | Integrates with | NOT STARTED |
| 016-Google Drive Integration             | Integrates with | NOT STARTED |
