# Collaboration Architecture

Taloflow's real-time collaboration is built on CRDTs (Conflict-free Replicated Data Types) via Y-WebSocket. This means multiple users can edit an evaluation simultaneously and their changes will always converge to a consistent state — with no merge conflicts and no data loss.

## What Is a CRDT?

A CRDT (Conflict-free Replicated Data Type) is a data structure specifically designed so that concurrent edits from multiple clients can always be merged automatically and deterministically. Unlike traditional operational transformation or "last write wins" strategies, CRDTs preserve every edit and reconcile them through mathematical guarantees rather than server-side arbitration.

{% hint style="info" %}
CRDTs are the same underlying approach used by Figma and Notion for their real-time collaboration models. The key property is convergence: regardless of network latency or the order edits arrive, every client will eventually reach the same state.
{% endhint %}

## Architecture Overview

```
User Browser A          User Browser B
     |                       |
     | wss:// (TLS)          | wss:// (TLS)
     v                       v
+---------------------------+
|      Y-WebSocket Server   |
|  - Receives CRDT updates  |
|  - Broadcasts to peers    |
|  - Persists to Redis      |
+---------------------------+
          |
          | HTTP POST (changes only)
          v
+---------------------------+
| Eval-Update Lambda        |
|  - Writes DB delta        |
|  - Stores S3 snapshot     |
|    (encrypted, SSE-C)     |
+---------------------------+
          |
     PostgreSQL + S3
```

### Component Responsibilities

| Component              | Role                                                                                                                                                    |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Y-WebSocket Server** | Receives CRDT update messages from connected browsers, broadcasts them to all peers in the session, and persists live state to Redis                    |
| **Redis**              | Holds the authoritative in-memory CRDT state for active collaboration sessions                                                                          |
| **Eval-Update Lambda** | Receives change notifications via HTTP POST, writes a structured delta to PostgreSQL, and periodically stores an encrypted full-document snapshot to S3 |
| **PostgreSQL**         | Stores evaluation metadata, structure, and deltas as durable relational records                                                                         |
| **S3**                 | Stores encrypted full-document snapshots for point-in-time recovery                                                                                     |

## Privacy Design of the Collaboration Layer

{% hint style="warning" %}
Evaluation payloads contain product assessments and feature data. They do not contain user PII. Identity within the collaboration layer is handled exclusively through anonymous UUIDs.
{% endhint %}

### Transport Security

All WebSocket connections use `wss://` — WebSocket Secure over TLS. Unencrypted WebSocket connections (`ws://`) are not permitted.

### Identity Within the Collaboration Layer

* All change attribution within an evaluation uses `member_id` (UUID) only.
* Email addresses, display names, and other PII are never embedded in CRDT update messages.
* Services that do not require user identity (evaluation resolver, catalog resolver) never receive PII.

### Application-Level Encryption for Snapshots

S3 snapshots are encrypted at two layers:

1. **Application layer**: The evaluation document is gzip-compressed, base64-encoded, and AES-encrypted before being written to S3.
2. **Server-side encryption**: S3 applies SSE-C (Server-Side Encryption with Customer-Provided Keys) as an additional layer.

### Lambda Data Isolation

The eval-update Lambda includes a `doNotProcessUpdates` flag that prevents the Lambda from re-ingesting its own output. This eliminates feedback loops in which a Lambda-written change triggers a new CRDT update, which triggers another Lambda invocation.

## What Is Persisted and When

| Data                                    | Storage        | Timing                                            |
| --------------------------------------- | -------------- | ------------------------------------------------- |
| Live CRDT state                         | Redis          | Continuously, during active collaboration session |
| Evaluation delta (structure + metadata) | PostgreSQL     | On each change, written by eval-update Lambda     |
| Full-document snapshot                  | S3 (encrypted) | Periodically, triggered by eval-update Lambda     |

{% hint style="info" %}
Redis state is ephemeral by design — it holds only the data needed for active sessions. PostgreSQL and S3 are the durable records of truth.
{% endhint %}

## Multi-User Scenarios

### Two users edit the same section simultaneously

Each browser generates a CRDT update locally and transmits it to the Y-WebSocket server. The server broadcasts both updates to all connected peers. Each client applies the remote update to its local CRDT. Because CRDTs are mathematically guaranteed to converge, both clients reach the same final state regardless of which update arrived first. No conflict dialog is shown; no data is lost.

### A user disconnects and reconnects

On reconnection, the Y-WebSocket server sends the client the full current CRDT state from Redis. If the Redis state has been evicted (session expired), the Lambda retrieves the most recent S3 snapshot, decrypts it, and restores the session state before reconnecting the client.

### A workspace with 50 concurrent editors

Y-WebSocket broadcasts updates as compact binary CRDT diff messages, not full document copies. Message size scales with the change, not the document size, so 50 concurrent editors produce 50 small diff broadcasts per change — not 50 full-document transmissions. Redis holds a single authoritative state object regardless of the number of connected clients.
