···1010type service = {type': string [@key "type"]; endpoint: string}
1111[@@deriving yojson {strict= false}]
12121313+type service_map = (string * service) list [@@deriving yojson {strict= false}]
1414+1515+let service_map_to_yojson map =
1616+ `Assoc (List.map (fun (k, v) -> (k, service_to_yojson v)) map)
1717+1818+let service_map_of_yojson = function
1919+ | `Assoc l ->
2020+ Ok
2121+ (List.map
2222+ (fun (k, v) ->
2323+ ( k
2424+ , match service_of_yojson v with
2525+ | Ok s ->
2626+ s
2727+ | Error _ ->
2828+ Yojson.json_error ("invalid service " ^ k) ) )
2929+ l )
3030+ | _ ->
3131+ Error "invalid service map"
3232+1333type credentials =
1434 { rotation_keys: string list [@key "rotationKeys"]
1515- ; verification_methods: (string * string) list [@key "verificationMethods"]
3535+ ; verification_methods: string_map [@key "verificationMethods"]
1636 ; also_known_as: string list [@key "alsoKnownAs"]
1717- ; services: (string * service) list [@key "services"] }
3737+ ; services: service_map }
1838[@@deriving yojson {strict= false}]
19392040type unsigned_operation_op =
2141 { type': string [@key "type"]
2242 ; rotation_keys: string list [@key "rotationKeys"]
2323- ; verification_methods: (string * string) list [@key "verificationMethods"]
4343+ ; verification_methods: string_map [@key "verificationMethods"]
2444 ; also_known_as: string list [@key "alsoKnownAs"]
2525- ; services: (string * service) list
2626- ; prev: string option }
4545+ ; services: service_map
4646+ ; prev: string_or_null }
2747[@@deriving yojson {strict= false}]
28482949type unsigned_tombstone_op = {type': string [@key "type"]; prev: string}
···3252type unsigned_operation =
3353 | Operation of unsigned_operation_op
3454 | Tombstone of unsigned_tombstone_op
3535-[@@deriving yojson {strict= false}]
36553756let unsigned_operation_to_yojson = function
3838- | Operation
3939- {type'; rotation_keys; verification_methods; also_known_as; services; prev}
4040- ->
4141- `Assoc
4242- [ ("type", `String type')
4343- ; ("rotationKeys", `List (List.map (fun k -> `String k) rotation_keys))
4444- ; ( "verificationMethods"
4545- , `Assoc
4646- (List.map
4747- (fun ((k, v) : string * string) -> (k, `String v))
4848- verification_methods ) )
4949- ; ("alsoKnownAs", `List (List.map (fun k -> `String k) also_known_as))
5050- ; ( "services"
5151- , `Assoc
5252- (List.map
5353- (fun ((k, v) : string * service) ->
5454- ( k
5555- , `Assoc
5656- [ ("type", `String v.type')
5757- ; ("endpoint", `String v.endpoint) ] ) )
5858- services ) )
5959- ; ("prev", match prev with Some p -> `String p | None -> `Null) ]
6060- | Tombstone {type'; prev} ->
6161- `Assoc [("type", `String type'); ("prev", `String prev)]
5757+ | Operation op ->
5858+ unsigned_operation_op_to_yojson op
5959+ | Tombstone op ->
6060+ unsigned_tombstone_op_to_yojson op
62616362let unsigned_operation_of_yojson (json : Yojson.Safe.t) =
6464- let open Yojson.Safe.Util in
6565- let type' = json |> member "type" |> to_string in
6666- let rotation_keys =
6767- json |> member "rotationKeys" |> to_list |> List.map to_string
6868- in
6969- let verification_methods =
7070- json
7171- |> member "verificationMethods"
7272- |> to_assoc
7373- |> List.map (fun (key, value) -> (key, to_string value))
7474- in
7575- let also_known_as =
7676- json |> member "alsoKnownAs" |> to_list |> List.map to_string
7777- in
7878- let services =
7979- json |> member "services" |> to_assoc
8080- |> List.map (fun (k, v) -> (k, Result.get_ok @@ service_of_yojson v))
8181- in
8282- let prev = json |> member "prev" |> to_string_option in
8383- match type' with
6363+ match Yojson.Safe.Util.(json |> member "type" |> to_string) with
8464 | "plc_operation" ->
8585- Ok
8686- (Operation
8787- { type'
8888- ; rotation_keys
8989- ; verification_methods
9090- ; also_known_as
9191- ; services
9292- ; prev } )
6565+ Result.map (fun op -> Operation op)
6666+ @@ unsigned_operation_op_of_yojson json
9367 | "plc_tombstone" ->
9494- Ok (Tombstone {type'; prev= Option.get prev})
9595- | _ ->
9696- Error ("invalid operation type " ^ type')
6868+ Result.map (fun op -> Tombstone op)
6969+ @@ unsigned_tombstone_op_of_yojson json
7070+ | typ ->
7171+ Error ("invalid operation type " ^ typ)
97729873type signed_operation_op =
9974 { type': string [@key "type"]
10075 ; rotation_keys: string list [@key "rotationKeys"]
101101- ; verification_methods: (string * string) list [@key "verificationMethods"]
7676+ ; verification_methods: string_map [@key "verificationMethods"]
10277 ; also_known_as: string list [@key "alsoKnownAs"]
103103- ; services: (string * service) list
104104- ; prev: string option
7878+ ; services: service_map
7979+ ; prev: string_or_null
10580 ; signature: string [@key "sig"] }
10681[@@deriving yojson {strict= false}]
10782···11287type signed_operation =
11388 | Operation of signed_operation_op
11489 | Tombstone of signed_tombstone_op
115115-[@@deriving yojson {strict= false}]
1169011791let signed_operation_to_yojson = function
118118- | Operation
119119- { type'
120120- ; rotation_keys
121121- ; verification_methods
122122- ; also_known_as
123123- ; services
124124- ; prev
125125- ; signature } -> (
126126- match
127127- unsigned_operation_to_yojson
128128- (Operation
129129- { type'
130130- ; rotation_keys
131131- ; verification_methods
132132- ; also_known_as
133133- ; services
134134- ; prev } )
135135- with
136136- | `Assoc fields ->
137137- `Assoc (fields @ [("sig", `String signature)])
138138- | _ ->
139139- failwith "unexpected json structure" )
140140- | Tombstone {type'; prev; signature} -> (
141141- match unsigned_operation_to_yojson (Tombstone {type'; prev}) with
142142- | `Assoc fields ->
143143- `Assoc (fields @ [("sig", `String signature)])
144144- | _ ->
145145- failwith "unexpected json structure" )
9292+ | Operation op ->
9393+ signed_operation_op_to_yojson op
9494+ | Tombstone op ->
9595+ signed_tombstone_op_to_yojson op
1469614797let signed_operation_of_yojson (json : Yojson.Safe.t) =
148148- let open Yojson.Safe.Util in
149149- let type' = json |> member "type" |> to_string in
150150- match type' with
9898+ match Yojson.Safe.Util.(json |> member "type" |> to_string) with
15199 | "plc_operation" ->
152152- let rotation_keys =
153153- json |> member "rotationKeys" |> to_list |> List.map to_string
154154- in
155155- let verification_methods =
156156- json
157157- |> member "verificationMethods"
158158- |> to_assoc
159159- |> List.map (fun (k, v) -> (k, to_string v))
160160- in
161161- let also_known_as =
162162- json |> member "alsoKnownAs" |> to_list |> List.map to_string
163163- in
164164- let services =
165165- json |> member "services" |> to_assoc
166166- |> List.map (fun (k, v) -> (k, Result.get_ok @@ service_of_yojson v))
167167- in
168168- let prev = json |> member "prev" |> to_string_option in
169169- let signature = json |> member "sig" |> to_string in
170170- Ok
171171- (Operation
172172- { type'
173173- ; rotation_keys
174174- ; verification_methods
175175- ; also_known_as
176176- ; services
177177- ; prev
178178- ; signature } )
100100+ Result.map (fun op -> Operation op) (signed_operation_op_of_yojson json)
179101 | "plc_tombstone" ->
180180- let prev = json |> member "prev" |> to_string in
181181- let signature = json |> member "sig" |> to_string in
182182- Ok (Tombstone {type'; prev; signature})
183183- | t ->
184184- Error ("unexpected operation type " ^ t)
102102+ Result.map (fun op -> Tombstone op) (signed_tombstone_op_of_yojson json)
103103+ | typ ->
104104+ Error ("unexpected operation type " ^ typ)
185105186106type audit_log_operation =
187107 { signature: string [@key "sig"]
188188- ; prev: string option [@default None]
108108+ ; prev: string_or_null
189109 ; type': string [@key "type"]
190190- ; services: (string * service) list
191191- [@to_yojson
192192- fun l -> `Assoc (List.map (fun (k, v) -> (k, service_to_yojson v)) l)]
193193- [@of_yojson
194194- function
195195- | `Assoc fields ->
196196- Ok
197197- (List.filter_map
198198- (fun (k, v) ->
199199- match service_of_yojson v with
200200- | Ok service ->
201201- Some (k, service)
202202- | _ ->
203203- None )
204204- fields )
205205- | _ ->
206206- Error "Expected object for services"]
110110+ ; services: service_map
207111 ; also_known_as: string list [@key "alsoKnownAs"]
208112 ; rotation_keys: string list [@key "rotationKeys"]
209113 ; verification_methods: string_map [@key "verificationMethods"] }
···286190 ; also_known_as= ["at://" ^ handle]
287191 ; services=
288192 [ ( "atproto_pds"
289289- , { type'= "AtprotoPersonalDataServer"
290290- ; endpoint= Env.host_endpoint } ) ] }
193193+ , {type'= "AtprotoPersonalDataServer"; endpoint= Env.host_endpoint} ) ]
194194+ }
291195292196let create_did (pds_rotation_key : Kleidos.key) (signing_did_key : string)
293197 ?(rotation_did_keys : string list option) handle : string * signed_operation
+12
pegasus/lib/util.ml
···8383end
84848585module Did_doc_types = struct
8686+ type string_or_null = string option
8787+8888+ let string_or_null_to_yojson = function Some s -> `String s | None -> `Null
8989+9090+ let string_or_null_of_yojson = function
9191+ | `String s ->
9292+ Ok (Some s)
9393+ | `Null ->
9494+ Ok None
9595+ | _ ->
9696+ Error "invalid field value"
9797+8698 type string_or_strings = [`String of string | `Strings of string list]
879988100 let string_or_strings_to_yojson = function