A real-time collaborative document editing backend built with Go. Features Operational Transformation (OT) for conflict-free concurrent editing, WebSocket communication, and role-based access control.
internal/
├── acl/ # Access control (Owner, Editor, Viewer roles)
├── collab/ # Session management and operation coordination
├── handler/ # HTTP handlers (REST + WebSocket)
├── ot/ # Operational Transformation engine
├── storage/ # Document persistence (in-memory)
└── ws/ # WebSocket client/hub management
- Go 1.21+
go run main.goThe server starts on http://localhost:8080.
All endpoints require the X-User-Id header for authentication.
curl -X POST http://localhost:8080/documents \
-H "Content-Type: application/json" \
-H "X-User-Id: alice" \
-d '{"id": "my-doc"}'Response: 201 Created
{"id": "my-doc"}curl http://localhost:8080/documents/my-doc \
-H "X-User-Id: alice"Response: 200 OK
{"id": "my-doc", "content": "hello", "revision": 5}curl -X DELETE http://localhost:8080/documents/my-doc \
-H "X-User-Id: alice"Response: 204 No Content
Connect to ws://localhost:8080/ws?docId={document-id} with the X-User-Id header.
Client to Server:
| Type | Description |
|---|---|
operation |
Submit an edit operation |
sync |
Request current document state |
Server to Client:
| Type | Description |
|---|---|
ack |
Confirms operation was applied |
broadcast |
Pushes another user's operation |
state |
Full document state |
error |
Error message |
{
"type": "operation",
"payload": {
"docId": "my-doc",
"baseRevision": 5,
"opType": 0,
"position": 5,
"char": "!"
}
}opType:0= insert,1= deleteposition: Character index in documentchar: Character to insert (omit for delete)baseRevision: Client's last known revision
# Install wscat if needed: npm install -g wscat
wscat -c "ws://localhost:8080/ws?docId=my-doc" -H "X-User-Id: alice"On connect, you receive the current state:
{"type":"state","payload":{"docId":"my-doc","content":"","revision":0}}Insert character "H" at position 0:
{"type":"operation","payload":{"docId":"my-doc","baseRevision":0,"opType":0,"position":0,"char":"H"}}Server acknowledges:
{"type":"ack","payload":{"revision":1}}Run all tests:
go test ./...Run tests with coverage:
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.outRun the coverage threshold check:
go-test-coverage --config=.testcoverage.ymlThe creator of a document is automatically granted the Owner role. Roles and permissions:
| Role | Read | Write | Delete |
|---|---|---|---|
| Owner | Yes | Yes | Yes |
| Editor | Yes | Yes | No |
| Viewer | Yes | No | No |
Users without any role cannot access the document (when ACL is enabled).
Operational Transformation ensures consistency when multiple users edit simultaneously:
- Each operation is tagged with a
baseRevision(the revision the client last saw) - The server transforms the operation against any concurrent operations
- The transformed operation is applied and assigned a new revision number
- The operation is broadcast to all other connected clients
This allows users to continue editing without waiting for server confirmation, while the server resolves conflicts automatically.
MIT