atproto libraries implementation in ocaml
1# Contributing to AT Protocol OCaml 2 3Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to the AT Protocol OCaml libraries. 4 5## Getting Started 6 7### Prerequisites 8 9- OCaml >= 5.1 (5.4 recommended) 10- opam >= 2.0 11- dune >= 3.20 12 13### Setting Up Development Environment 14 15```bash 16# Clone the repository 17git clone https://github.com/gdiazlo/atproto.git 18cd atproto 19 20# Install dependencies 21opam install . --deps-only --with-test 22 23# Build the project 24dune build 25 26# Run tests 27dune runtest 28``` 29 30## Project Structure 31 32``` 33atproto/ 34├── lib/ # Library source code 35│ ├── api/ # High-level API client 36│ ├── crypto/ # Cryptographic operations 37│ ├── effects/ # I/O effect abstractions 38│ ├── identity/ # DID/Handle resolution 39│ ├── ipld/ # DAG-CBOR, CIDs, CAR files 40│ ├── lexicon/ # Schema parsing/validation 41│ ├── mst/ # Merkle Search Tree 42│ ├── multibase/ # Base encoding 43│ ├── repo/ # Repository operations 44│ ├── sync/ # Firehose and sync 45│ ├── syntax/ # Identifier parsing 46│ └── xrpc/ # XRPC client/server 47├── test/ # Test suites 48│ ├── fixtures/ # Test data (atproto-interop-tests) 49│ └── */ # Per-package tests 50├── examples/ # Example applications 51└── dune-project # Project configuration 52``` 53 54## Development Workflow 55 56### Running Tests 57 58```bash 59# Run all tests 60dune runtest 61 62# Run tests for a specific package 63dune runtest test/syntax 64 65# Run with verbose output 66dune runtest --force --verbose 67 68# Run a specific test file 69dune exec test/syntax/test_syntax.exe 70``` 71 72### Code Formatting 73 74We use ocamlformat for consistent code style: 75 76```bash 77# Format all files 78dune fmt 79 80# Check formatting without modifying 81dune fmt --preview 82``` 83 84The project uses the default ocamlformat configuration (see `.ocamlformat`). 85 86### Building Documentation 87 88```bash 89# Build API documentation 90dune build @doc 91 92# Open in browser 93open _build/default/_doc/_html/index.html 94``` 95 96## Coding Guidelines 97 98### General Principles 99 1001. **Functional first** - Prefer immutable data structures and pure functions 1012. **Type safety** - Use the type system to prevent errors at compile time 1023. **No regex** - All syntax validation uses hand-written parsers 1034. **Effects for I/O** - Use the effects system for all I/O operations 104 105### Module Structure 106 107Each package follows a consistent structure: 108 109``` 110lib/packagename/ 111├── dune # Build configuration 112├── atproto_packagename.ml # Public interface (re-exports) 113├── module1.ml # Implementation 114├── module1.mli # Interface (optional but recommended) 115└── ... 116``` 117 118### Code Style 119 120```ocaml 121(* Use descriptive names *) 122let validate_handle s = ... 123 124(* Document public functions *) 125(** [of_string s] parses [s] as a handle. 126 Returns [Error msg] if the string is not a valid handle. *) 127val of_string : string -> (t, string) result 128 129(* Prefer Result over exceptions for expected errors *) 130let parse input = 131 match ... with 132 | Some v -> Ok v 133 | None -> Error "invalid input" 134 135(* Use labeled arguments for clarity when appropriate *) 136let create ~did ~handle ~service_endpoint = ... 137``` 138 139### Error Handling 140 141- Use `Result` for recoverable errors 142- Use `Option` for optional values 143- Reserve exceptions for programming errors (bugs) 144- Provide descriptive error messages 145 146### Testing 147 148- Every module should have corresponding tests 149- Use the interop test fixtures where applicable 150- Test edge cases and error conditions 151- Structure tests with clear descriptions 152 153```ocaml 154let test_handle_valid () = 155 let cases = ["alice.bsky.social"; "test.example.com"] in 156 List.iter (fun s -> 157 match Handle.of_string s with 158 | Ok _ -> () 159 | Error e -> Alcotest.fail (Printf.sprintf "%s: %s" s e) 160 ) cases 161 162let () = 163 Alcotest.run "Handle" [ 164 "parsing", [ 165 Alcotest.test_case "valid handles" `Quick test_handle_valid; 166 Alcotest.test_case "invalid handles" `Quick test_handle_invalid; 167 ]; 168 ] 169``` 170 171## Making Changes 172 173### Before You Start 174 1751. Check existing issues to avoid duplicate work 1762. For large changes, open an issue first to discuss the approach 1773. Make sure you understand the AT Protocol specs at [atproto.com](https://atproto.com/specs) 178 179### Pull Request Process 180 1811. **Fork and branch** - Create a feature branch from `main` 182 ```bash 183 git checkout -b feature/my-feature 184 ``` 185 1862. **Make changes** - Follow the coding guidelines above 187 1883. **Test** - Ensure all tests pass 189 ```bash 190 dune runtest 191 ``` 192 1934. **Format** - Run the formatter 194 ```bash 195 dune fmt 196 ``` 197 1985. **Commit** - Write clear commit messages 199 ``` 200 Add handle resolution via DNS TXT records 201 202 Implements DNS-based handle resolution as specified in 203 the AT Protocol identity spec. Includes tests using 204 fixtures from atproto-interop-tests. 205 ``` 206 2076. **Push and PR** - Open a pull request with: 208 - Clear description of changes 209 - Reference to related issues 210 - Test coverage for new functionality 211 212### Commit Message Format 213 214``` 215<type>: <short summary> 216 217<detailed description if needed> 218 219<references> 220``` 221 222Types: 223- `feat` - New feature 224- `fix` - Bug fix 225- `docs` - Documentation only 226- `test` - Adding or updating tests 227- `refactor` - Code change that doesn't fix a bug or add a feature 228- `chore` - Maintenance tasks 229 230## Working with the AT Protocol Spec 231 232### Key Resources 233 234- [AT Protocol Specification](https://atproto.com/specs) 235- [Lexicon Reference](https://atproto.com/specs/lexicon) 236- [Data Model](https://atproto.com/specs/data-model) 237- [Repository Spec](https://atproto.com/specs/repository) 238 239### Interop Tests 240 241The test fixtures in `test/fixtures/` come from the official 242[atproto-interop-tests](https://github.com/bluesky-social/atproto-interop-tests) repository. 243 244To update fixtures: 245 246```bash 247cd test/fixtures 248git pull origin main 249``` 250 251When implementing new functionality, check if there are relevant fixtures to test against. 252 253## Package-Specific Notes 254 255### atproto-syntax 256 257- No regex - all parsing is done with hand-written parsers 258- Each identifier type has `of_string`, `to_string`, and validation 259- Follow the exact spec for character sets and lengths 260 261### atproto-crypto 262 263- Uses `mirage-crypto-ec` for P-256 264- Uses `secp256k1-ml` indirectly via custom K-256 wrapper 265- Always apply low-S normalization to signatures 266- did:key encoding must match multicodec spec exactly 267 268### atproto-ipld 269 270- DAG-CBOR keys must be sorted by length, then lexicographically 271- CIDs use SHA-256 and base32lower encoding 272- Support both CIDv0 and CIDv1 273 274### atproto-effects 275 276- Define effect types for all I/O operations 277- Keep effect handlers separate from business logic 278- Test with mock handlers, deploy with real handlers 279 280## Questions? 281 282- Open an issue for questions about the codebase 283- Check the AT Protocol Discord for protocol questions 284- Review the reference TypeScript implementation for clarification 285 286## License 287 288By contributing, you agree that your contributions will be licensed under the MIT License.