JSON web tokens in OCaml

Documentation and code quality improvements across libraries

- Add README files for jsonwt, owntracks, monopam, and srcsetter
- Fix langdetect language count (47→49) in dune-project
- Remove unused variable in crockford encode function
- Improve retention type documentation in zulip channels.mli
- Refactor conpool is_healthy to reduce nesting and improve clarity
- Document unimplemented IDNA features in punycode README

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+74
+74
README.md
···
··· 1 + # jsonwt 2 + 3 + JSON Web Token (JWT) and CBOR Web Token (CWT) implementation for OCaml. 4 + 5 + ## Overview 6 + 7 + A type-safe implementation of JWT (RFC 7519) and CWT (RFC 8392) with full support for: 8 + 9 + - **JWT parsing and creation** - Compact serialization format 10 + - **Signature verification** - HMAC, RSA, ECDSA, and EdDSA algorithms 11 + - **Claims validation** - Expiration, not-before, issuer, audience checks 12 + - **JSON Web Key (JWK)** - Key representation per RFC 7517 13 + - **Nested JWTs** - Recursive parsing with depth limits 14 + - **CBOR Web Tokens** - RFC 8392 for constrained environments 15 + 16 + ## Installation 17 + 18 + ``` 19 + opam install jsonwt 20 + ``` 21 + 22 + ## Usage 23 + 24 + ### Parsing and Verifying a JWT 25 + 26 + ```ocaml 27 + let token_string = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." in 28 + match Jsonwt.parse token_string with 29 + | Ok jwt -> 30 + let key = Jsonwt.Jwk.symmetric "secret-key" in 31 + (match Jsonwt.verify ~key jwt with 32 + | Ok () -> print_endline "Valid signature" 33 + | Error e -> print_endline (Jsonwt.error_to_string e)) 34 + | Error e -> print_endline (Jsonwt.error_to_string e) 35 + ``` 36 + 37 + ### Creating a JWT 38 + 39 + ```ocaml 40 + let header = Jsonwt.Header.make ~typ:"JWT" Jsonwt.Algorithm.HS256 in 41 + let claims = Jsonwt.Claims.( 42 + empty 43 + |> set_iss "https://example.com" 44 + |> set_sub "user123" 45 + |> set_exp (Ptime.of_float_s 1700000000.0 |> Option.get) 46 + |> build 47 + ) in 48 + let key = Jsonwt.Jwk.symmetric "secret-key" in 49 + match Jsonwt.create ~header ~claims ~key with 50 + | Ok jwt -> print_endline (Jsonwt.encode jwt) 51 + | Error e -> print_endline (Jsonwt.error_to_string e) 52 + ``` 53 + 54 + ## Supported Algorithms 55 + 56 + | Algorithm | Description | 57 + |-----------|-------------| 58 + | HS256/384/512 | HMAC with SHA-2 | 59 + | RS256/384/512 | RSASSA-PKCS1-v1_5 with SHA-2 | 60 + | ES256/384/512 | ECDSA with P-256/384/521 | 61 + | EdDSA | Ed25519 signatures | 62 + | none | Unsecured (requires explicit opt-in) | 63 + 64 + ## References 65 + 66 + - [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) - JSON Web Token (JWT) 67 + - [RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515) - JSON Web Signature (JWS) 68 + - [RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517) - JSON Web Key (JWK) 69 + - [RFC 7518](https://datatracker.ietf.org/doc/html/rfc7518) - JSON Web Algorithms (JWA) 70 + - [RFC 8392](https://datatracker.ietf.org/doc/html/rfc8392) - CBOR Web Token (CWT) 71 + 72 + ## License 73 + 74 + ISC