AT Protocol Implementation Guide#
This guide provides comprehensive information about implementing AT Protocol (atproto) in the Coves platform.
Table of Contents#
- Core Concepts
- Architecture Overview
- Lexicons
- XRPC
- Data Storage
- Identity & Authentication
- Firehose & Sync
- Go Implementation Patterns
- Best Practices
Core Concepts#
What is AT Protocol?#
AT Protocol is a federated social networking protocol that enables:
- Decentralized identity - Users own their identity (DID) and can move between providers
- Data portability - Users can export and migrate their full social graph and content
- Interoperability - Different apps can interact with the same underlying data
Key Components#
- DIDs (Decentralized Identifiers) - Persistent user identifiers (e.g.,
did:plc:xyz123) - Handles - Human-readable names that resolve to DIDs (e.g.,
alice.bsky.social) - Repositories - User data stored in PDS'
- Lexicons - Schema definitions for data types and API methods
- XRPC - The RPC protocol for client-server communication
- Firehose - Real-time event stream of repository changes
Architecture Overview#
Coves Architecture Pattern#
Coves uses a simplified, single-database architecture that leverages existing atProto infrastructure:
Components#
-
PDS (Personal Data Server)
- Managed by Bluesky's official PDS implementation
- Handles user repositories, DIDs, and CAR file storage
- Users can use our PDS or any external PDS (federated)
- Emits events to the Relay/firehose
-
Relay (BigSky)
- Aggregates firehose events from multiple PDSs
- For development: subscribes only to local dev PDS
- For production: can subscribe to multiple PDSs or public relay
-
AppView Database (Single PostgreSQL)
- Purpose: Denormalized, indexed data optimized for Coves queries
- Storage: PostgreSQL with Coves-specific schema
- Contains:
- Indexed posts, communities, feeds
- User read states and preferences
- PDS metadata and record references
- Properties:
- Eventually consistent with PDS repositories
- Can be rebuilt from firehose replay
- Application-specific aggregations
-
Coves AppView (Go Application)
- Subscribes to Relay firehose
- Indexes relevant records into PostgreSQL
- Serves XRPC queries for Coves features
- Implements custom feed algorithms
Data Flow#
Write Path:
Client → PDS (via XRPC) → Repository Record Created
↓
Firehose Event
↓
Relay aggregates events
↓
Coves AppView subscribes
↓
Index in PostgreSQL
Read Path:
Client → Coves AppView (via XRPC) → PostgreSQL Query → Response
Key Point: Coves AppView only reads from the firehose and indexes data. It does NOT write to CAR files or manage repositories directly - the PDS handles that.
Lexicons#
What are Lexicons?#
Lexicons are JSON schema files that define:
- Data types (records stored in repositories)
- API methods (queries and procedures)
- Input/output schemas for API calls
Lexicon Structure#
{
"lexicon": 1,
"id": "social.coves.community.profile",
"defs": {
"main": {
"type": "record",
"key": "self",
"record": {
"type": "object",
"required": ["name", "createdAt"],
"properties": {
"name": {"type": "string", "maxLength": 64},
"description": {"type": "string", "maxLength": 256},
"rules": {"type": "array", "items": {"type": "string"}},
"createdAt": {"type": "string", "format": "datetime"}
}
}
}
}
}
Lexicon Types#
1. Record Types#
Define data structures stored in user repositories:
{
"type": "record",
"key": "tid|rkey|literal",
"record": { /* schema */ }
}
2. Query Types (Read-only)#
Define read operations that don't modify state:
{
"type": "query",
"parameters": { /* input schema */ },
"output": { /* response schema */ }
}
3. Procedure Types (Write)#
Define operations that modify repositories:
{
"type": "procedure",
"input": { /* request body schema */ },
"output": { /* response schema */ }
}
Naming Conventions#
- Use reverse-DNS format:
social.coves.community.profile - Queries often start with
get,list, orsearch - Procedures often start with
create,update, ordelete - Keep names descriptive but concise
Identity & Authentication#
DIDs (Decentralized Identifiers)#
- Permanent, unique identifiers for users
- Two types supported:
did:plc:*- Hosted by PLC Directorydid:web:*- Self-hosted
Handle Resolution#
Handles resolve to DIDs via:
- DNS TXT record:
_atproto.alice.com → did:plc:xyz - HTTPS well-known:
https://alice.com/.well-known/atproto-did
Authentication Flow#
- Client creates session with OAuth
Firehose & Sync#
Firehose Events#
Real-time stream of repository changes:
- Commit events (creates, updates, deletes)
- Identity events (handle changes)
- Account events (status changes)
Subscribing to Firehose#
Connect via WebSocket to com.atproto.sync.subscribeRepos:
wss://bsky.network/xrpc/com.atproto.sync.subscribeRepos
Processing Events#
- Events include full record data and operation type
- Process events to update AppView database
- Handle out-of-order events with sequence numbers
Go Implementation Patterns#
Using Indigo Library#
Bluesky's official Go implementation provides:
- Lexicon code generation
- XRPC client/server
- Firehose subscription
Code Generation#
Generate Go types from Lexicons:
go run github.com/bluesky-social/indigo/cmd/lexgen \
--package coves \
--prefix social.coves \
--outdir api/coves \
lexicons/social/coves/*.json
Repository Operations#
// Write to repository
rkey := models.GenerateTID()
err := repoStore.CreateRecord(ctx, userDID, "social.coves.post", rkey, &Post{
Text: "Hello",
CreatedAt: time.Now().Format(time.RFC3339),
})
// Read from repository
records, err := repoStore.ListRecords(ctx, userDID, "social.coves.post", limit, cursor)
XRPC Handler Pattern#
func (s *Server) HandleGetCommunity(ctx context.Context) error {
// 1. Parse and validate input
id := xrpc.QueryParam(ctx, "id")
// 2. Call service layer
community, err := s.communityService.GetByID(ctx, id)
if err != nil {
return err
}
// 3. Return response
return xrpc.WriteJSONResponse(ctx, community)
}
Best Practices#
1. Lexicon Design#
- Keep schemas focused and single-purpose
- Use references (
$ref) for shared types - Version carefully - Lexicons are contracts
- Document thoroughly with descriptions
2. Data Modeling#
- Store minimal data in repositories
- Denormalize extensively in AppView
- Use record keys that are meaningful
- Plan for data portability
3. Performance#
- Batch firehose processing
- Use database transactions wisely
- Index AppView tables appropriately
- Cache frequently accessed data
4. Error Handling#
- Use standard XRPC error codes
- Provide meaningful error messages
- Handle network failures gracefully
- Implement proper retry logic
5. Security#
- Validate all inputs against Lexicons
- Verify signatures on repository data
- Rate limit API endpoints
- Sanitize user-generated content
6. Federation#
- Design for multi-instance deployment
- Handle remote user identities
- Respect instance-specific policies
- Plan for cross-instance data sync
Common Patterns#
Handling User Content#
- Always validate against Lexicon schemas
- Store in user's repository via CAR files
- Index in AppView for efficient queries
- Emit firehose events for subscribers