Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/arrozet/caret/llms.txt

Use this file to discover all available pages before exploring further.

Caret’s backend is composed of five independently deployed services. Four are written in TypeScript and run on Node.js using the Bun runtime; the fifth is a Python FastAPI application managed with uv. Each service owns a single domain of responsibility and exposes its own API documentation endpoint. All services share the same Supabase Cloud PostgreSQL database and validate Supabase JWTs for request authentication.

Service Overview

ServiceStackPortRole
api-gatewayExpress 5 + TypeScript3000Public REST entrypoint, CORS, rate limiting, proxy routing
auth-serviceExpress 5 + TypeScript3001Auth API surface and OpenAPI metadata
document-serviceExpress 5 + TypeScript + Drizzle3002Workspaces, folders, documents, members, versions
collab-serviceNode HTTP + ws + Y.js3003Direct WebSocket collaboration and awareness
ai-serviceFastAPI + SQLAlchemy async + PydanticAI8000AI chat, SSE streaming, suggestions, embeddings/RAG
All Node services follow the same layer split convention:
route / controller / handler
      → service
      → repository
      → db / model / schema
Route handlers parse HTTP or WebSocket boundaries and validate inputs. Services contain business rules and protocol orchestration. Repositories handle all SQL and ORM access — no HTTP concepts leak into the data layer. Never import Drizzle or SQLAlchemy directly into a route handler.

API Gateway (port 3000)

The API Gateway is the single public entrypoint for all REST and SSE traffic from the frontend. It is the only service exposed to the public internet via api.caret.page. Stack: Express 5 + TypeScript, built and run with Bun. Responsibilities:
  • Apply CORS headers and rate limiting before traffic reaches downstream services.
  • Proxy incoming requests at /api/v1/... to the correct downstream service based on path prefix.
  • Serve the aggregated OpenAPI spec and docs UI so API consumers have one URL to visit.
Proxy routing table:
Path prefixDownstream service
/api/v1/authauth-service (port 3001)
/api/v1/documentsdocument-service (port 3002)
/api/v1/workspacesdocument-service (port 3002)
/api/v1/foldersdocument-service (port 3002)
/api/v1/aiai-service (port 8000)
API docs: OpenAPI spec at /openapi.json, interactive docs UI at /docs.
WebSocket connections for collaboration are not routed through the API Gateway. The frontend opens a direct WebSocket connection to the collab-service. See Auth & Security for how the JWT is passed on the WebSocket handshake.

Auth Service (port 3001)

The Auth Service is intentionally lightweight. Supabase Auth is the real authentication engine; this service exists to provide a consistent auth API surface behind the gateway and to expose OpenAPI documentation for auth-related contracts. Stack: Express 5 + TypeScript, built and run with Bun. Responsibilities:
  • Respond to health check requests from the gateway and infrastructure probes.
  • Expose OpenAPI metadata for auth-related endpoints (login, logout, token refresh contracts).
  • Mount error-handling middleware and shared auth controller stubs.
Runtime note: Most auth controller files in this service are currently metadata controllers used to generate the OpenAPI spec. Runtime auth enforcement (JWT validation, session management) happens at each individual service using SUPABASE_JWT_SECRET. API docs: Interactive docs UI at /docs.

Document Service (port 3002)

The Document Service is the primary CRUD service for all user content organization. It owns workspaces, folders, documents, document memberships, and document version history. Stack: Express 5 + TypeScript + Drizzle ORM, built and run with Bun. Responsibilities:
  • Manage workspace creation, membership, and settings.
  • Manage hierarchical folder trees within workspaces.
  • Manage document metadata, visibility, sharing permissions, and lifecycle status.
  • Create and retrieve immutable document version snapshots (ProseMirror JSON + plain text).
  • Enforce workspace-scoped and document-scoped RBAC through service logic and RLS policies.
Directory layout:
document-service/src/
  app.ts
  controllers/       # tsoa metadata controllers
  routes/            # Express runtime route handlers
  services/          # Business rules and orchestration
  repositories/      # All Drizzle/PostgreSQL access
  db/
    schema.ts        # Drizzle table definitions
    migrations/      # SQL migration files (incl. RLS policies)
  dtos/              # Request/response typed shapes
  middleware/
Schema summary (tables owned by this service): workspaces, workspace_members, folders, documents, document_members, document_versions, user_profiles. See Database for the full schema. Migrations: Drizzle-managed SQL migrations live in src/db/migrations/. Run bun run drizzle commands from the service directory. API docs: Interactive docs UI at /docs.

Collab Service (port 3003)

The Collab Service enables real-time collaborative editing using the Y.js CRDT protocol. It is the only service that accepts WebSocket connections from the frontend and the only service not behind the API Gateway. Stack: Node.js HTTP server + ws WebSocket library + Y.js, built and run with Bun. WebSocket endpoint: ws://localhost:3003/document/{doc_id}?token={jwt} (production: wss://ws.caret.page/document/{doc_id}?token={jwt}) Responsibilities:
  • Validate the Supabase JWT on WebSocket handshake before allowing connection.
  • Maintain an in-memory Y.Doc per active document room.
  • Implement Y.js sync protocol (message type 0) and awareness protocol (message type 1).
  • Persist Y.js update payloads to document_collab_updates when DATABASE_URL is configured.
  • Run SnapshotScheduler to periodically save full-state snapshots to document_collab_snapshots.
  • Keep empty rooms alive in memory briefly so short disconnects don’t lose in-flight state.
Key internal components:
ComponentResponsibility
RoomManagerCreates and tracks in-memory Y.Doc instances per document
ConnectionHandlerHandles WebSocket frame parsing, Y.js message routing, and update persistence
CollabRepositoryAll SQL access for document_collab_updates and document_collab_snapshots
CollabPersistenceServiceReconstructs a Y.Doc from the latest snapshot plus incremental updates
SnapshotSchedulerPeriodically snapshots active in-memory rooms to the database
API docs: AsyncAPI spec at /asyncapi.json, AsyncAPI docs UI at /docs.
Persistence is partially wired. When DATABASE_URL is set, incoming Y.js updates are saved and periodic snapshots are scheduled. However, RoomManager currently initializes new rooms from a fresh Y.Doc and does not yet call CollabPersistenceService.loadDocument on startup. This means persisted state is not restored when a server restarts or when a room is created for the first time after a crash.

AI Service (port 8000)

The AI Service handles all agentic capabilities: conversational chat, document-aware suggestions, SSE token streaming, and vector embedding for RAG retrieval. It is written in Python and runs separately from the Node services. Stack: Python + FastAPI + PydanticAI + SQLAlchemy async + Alembic, managed with uv. Responsibilities:
  • Manage AI conversation sessions and message history.
  • Stream AI responses token-by-token over SSE to the frontend.
  • Generate and store document chunk embeddings in document_embeddings (pgvector).
  • Perform workspace-scoped semantic search to inject RAG context into agent prompts.
  • Manage the suggestion lifecycle (proposed → applied / dismissed / superseded).
Router breakdown:
RouterPath prefixResponsibility
ai_router/ai/conversationsConversation CRUD, message history, and SSE streaming (/{conversation_id}/stream)
meta_router/ai/modelsList available LLM models; no authentication required
embedding_router/ai/embeddingsIndex, search, and delete document embeddings
suggestion_router/ai/suggestionsSuggestion create, list, and status transitions
Agent types:
AgentPurpose
general_agentWriting assistance, paraphrasing, drafting, summarization
analyst_agentDocument analysis, metrics, structured data extraction
Directory layout:
ai-service/src/
  main.py
  routers/       # FastAPI route definitions (ai_router, embedding_router, suggestion_router)
  services/      # AIAgentService, EmbeddingService, etc.
  repositories/  # SQLAlchemy async DB access
  models/        # SQLAlchemy ORM models (ai.py)
  schemas/       # Pydantic request/response schemas
  db/            # Async engine and session factory
  core/          # Config, dependencies, lifespan
  agents/        # PydanticAI agent definitions
Migrations: Alembic manages all schema changes for AI service tables. Migration versions live in src/db/migrations/versions/. API docs: FastAPI native docs at /docs (Swagger UI) and /redoc.
The AI service never writes directly to document content tables. The consistency contract is:
  1. AI streams text chunks to the frontend via SSE.
  2. The frontend applies chunks or suggestions through Tiptap editor transactions.
  3. Tiptap / Y.js propagates the collaborative state to all connected clients.

Build docs developers (and LLMs) love