Supply Chain Integrity, Transparency, and Trust (IETF SCITT)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-cbor: decouple Codec from Value, namespace under Cbor.Codec, rename IO verbs

The codec record drops its Value.t-based [encode] / [decode] fields, leaving
[{ kind; encode_rw; decode_rw }] — codecs now write to a Binary.encoder and
read from a Binary.decoder directly, building 'a from bytes without an
intermediate Value.t. This satisfies the ocaml-encodings skill's "codec.ml
does not depend on value.ml" rule; only cbor.ml bridges the two via
[Binary.read_cbor] / [write_cbor].

Surface follows RFC 8949 spec order: cbor.mli sections walk major types 0-7,
then simple values (3.3) and tags (3.4), each linking to the relevant clause.
Combinators move under [Cbor.Codec] (was top-level on [Cbor]); naming tracks
CDDL: [Cbor.Obj] -> [Cbor.Codec.Map], [Cbor.Obj_int] -> [Cbor.Codec.Map_int],
[Cbor.string] -> [Cbor.Codec.text], [Cbor.string_map] -> [Cbor.Codec.text_map].

Top-level IO verbs follow the parallel naming convention used elsewhere in the
monorepo: [encode_string] / [decode_string] -> [to_string] / [of_string];
[Cbor.Private.{decode,encode}_cbor] collapse into [Cbor.{decode,encode}].
[update_mem] and [delete_mem] move out of [Codec] into [Cbor] as Value.t
patch helpers (they cannot be pure-stream codecs).

Includes a fix to [Binary.skip] for definite-length text/bytes (it was
unconditionally calling [skip_break], which fired on the next item's header).

297 cbor tests + mdx pass; 16 downstream callers (cose, jwt/cwt, mst, scitt,
irmin/cbor) migrated and pass tests.

+26 -29
+2 -2
lib/atp/scitt_atp.ml
··· 192 192 (List.of_seq (Irmin.Heap.to_seq proof.heap))); 193 193 ] 194 194 in 195 - let encoded_proof = Cbor.encode_string Cbor.any proof_cbor in 195 + let encoded_proof = Cbor.to_string Cbor.any proof_cbor in 196 196 let vdp_cbor = 197 197 Cbor.Value.array 198 198 [ Cbor.Value.string rk; Cbor.Value.bytes encoded_proof ] 199 199 in 200 - let vdp_bytes = Cbor.encode_string Cbor.any vdp_cbor in 200 + let vdp_bytes = Cbor.to_string Cbor.any vdp_cbor in 201 201 let root_raw = Atp.Cid.to_raw_bytes tree_root in 202 202 Ok 203 203 {
+2 -2
lib/proof.ml
··· 142 142 (* Verify the inner [before, after, blocks] proof structure once we already 143 143 know [repo_key] matches expectations. *) 144 144 let verify_mst_inner ~hash ~expected_leaf ~root ~repo_key proof_bytes = 145 - match Cbor.decode_string Cbor.any proof_bytes with 145 + match Cbor.of_string Cbor.any proof_bytes with 146 146 | Error _ -> Error "MST proof: invalid CBOR" 147 147 | Ok proof_arr -> ( 148 148 match Cbor.Value.to_array proof_arr with ··· 171 171 let verify_mst ~hash ~expected_leaf ~expected_repo_key ~root path = 172 172 match path with 173 173 | [ vdp_data ] -> ( 174 - match Cbor.decode_string Cbor.any vdp_data with 174 + match Cbor.of_string Cbor.any vdp_data with 175 175 | Error _ -> Error "MST vdp: invalid CBOR" 176 176 | Ok vdp_cbor -> ( 177 177 match Cbor.Value.to_array vdp_cbor with
+5 -8
lib/scitt.ml
··· 102 102 (** Check a CBOR map for duplicate keys by serializing each key to bytes. 103 103 Catches duplicates regardless of CBOR major type. *) 104 104 let cbor_check_unique_keys pairs = 105 - let key_bytes = 106 - List.map (fun (k, _) -> Cbor.encode_string Cbor.any k) pairs 107 - in 105 + let key_bytes = List.map (fun (k, _) -> Cbor.to_string Cbor.any k) pairs in 108 106 let unique = List.sort_uniq String.compare key_bytes in 109 107 if List.length key_bytes <> List.length unique then 110 108 Error "duplicate keys in CBOR map" ··· 387 385 receipt_payload r = 388 386 let ( let* ) = Result.bind in 389 387 let* cbor = 390 - Cbor.decode_string Cbor.any receipt_payload 388 + Cbor.of_string Cbor.any receipt_payload 391 389 |> Result.map_error (fun _ -> Invalid_receipt "bad receipt payload CBOR") 392 390 in 393 391 (* Parse and validate the CBOR map once, then extract all fields from ··· 593 591 (fun (_, _, cose) -> Cbor.Value.bytes (Cose.Sign1.encode cose)) 594 592 t.receipts) 595 593 in 596 - Cbor.encode_string Cbor.any 597 - (Cbor.Value.array [ signed_cbor; receipts_cbor ]) 594 + Cbor.to_string Cbor.any (Cbor.Value.array [ signed_cbor; receipts_cbor ]) 598 595 599 596 let decode s = 600 597 let ( let* ) = Result.bind in 601 598 let* cbor = 602 - Cbor.decode_string Cbor.any s 599 + Cbor.of_string Cbor.any s 603 600 |> Result.map_error (fun e -> 604 601 Invalid_statement (Fmt.str "%a" Cbor.Error.pp e)) 605 602 in ··· 753 750 let* ts = monotonic_now t in 754 751 let ts_str = Fmt.str "%a" (Ptime.pp_rfc3339 ()) ts in 755 752 let receipt_payload = 756 - Cbor.encode_string Cbor.any 753 + Cbor.to_string Cbor.any 757 754 (Cbor.Value.map 758 755 [ 759 756 (Cbor.Value.string "subject", Cbor.Value.string subject);
+3 -3
lib/vds.ml
··· 310 310 Cbor.Value.array [ Cbor.Value.string k; Cbor.Value.bytes v ]) 311 311 entries) 312 312 in 313 - Cbor.encode_string Cbor.any 313 + Cbor.to_string Cbor.any 314 314 (Cbor.Value.map 315 315 [ 316 316 (Cbor.Value.string "version", Cbor.Value.int 1); ··· 558 558 | None -> Error "import: not a CBOR map" 559 559 | Some pairs -> 560 560 let key_bytes = 561 - List.map (fun (k, _) -> Cbor.encode_string Cbor.any k) pairs 561 + List.map (fun (k, _) -> Cbor.to_string Cbor.any k) pairs 562 562 in 563 563 let unique = List.sort_uniq String.compare key_bytes in 564 564 if List.length key_bytes <> List.length unique then ··· 568 568 let parse_import_header data = 569 569 let ( let* ) = Result.bind in 570 570 let* cbor = 571 - Cbor.decode_string Cbor.any data 571 + Cbor.of_string Cbor.any data 572 572 |> Result.map_error (fun _ -> "import: invalid CBOR") 573 573 in 574 574 let* pairs = require_unique_cbor_map cbor in
+2 -2
test/atp/test_scitt_atp.ml
··· 481 481 let proof = Scitt.Receipt.inclusion_proof receipt in 482 482 match proof.path with 483 483 | [ vdp_data ] -> ( 484 - match Cbor.decode_string Cbor.any vdp_data with 484 + match Cbor.of_string Cbor.any vdp_data with 485 485 | Error _ -> Alcotest.fail "vdp decode failed" 486 486 | Ok cbor -> ( 487 487 match Cbor.Value.to_array cbor with ··· 524 524 let proof = Scitt.Receipt.inclusion_proof receipt in 525 525 match proof.path with 526 526 | [ vdp ] -> ( 527 - match Cbor.decode_string Cbor.any vdp with 527 + match Cbor.of_string Cbor.any vdp with 528 528 | Ok cbor -> ( 529 529 match Cbor.Value.to_array cbor with 530 530 | Some (k :: _) -> Option.value ~default:"" (Cbor.Value.to_text k)
+1 -1
test/gen/interop_check.ml
··· 72 72 | Some proof_bstr -> ( 73 73 Fmt.pr " proof bstr (%d bytes)\n" 74 74 (String.length proof_bstr); 75 - match Cbor.decode_string Cbor.any proof_bstr with 75 + match Cbor.of_string Cbor.any proof_bstr with 76 76 | Error _ -> Fmt.pr " CBOR decode failed\n" 77 77 | Ok proof_cbor -> ( 78 78 match Cbor.Value.to_array proof_cbor with
+10 -10
test/test_scitt.ml
··· 558 558 let signed_cbor = Cbor.Value.bytes (Scitt.Signed_statement.encode signed) in 559 559 let receipts_cbor = Cbor.Value.array [ Cbor.Value.bytes truncated ] in 560 560 let ts_cbor = Cbor.Value.array [ signed_cbor; receipts_cbor ] in 561 - let ts_bytes = Cbor.encode_string Cbor.any ts_cbor in 561 + let ts_bytes = Cbor.to_string Cbor.any ts_cbor in 562 562 match Scitt.Transparent_statement.decode ts_bytes with 563 563 | Ok _ -> Alcotest.fail "should reject truncated receipt" 564 564 | Error _ -> () ··· 1470 1470 match Cbor.Value.to_bytes proof_bstr with 1471 1471 | None -> Alcotest.fail "proof not bstr" 1472 1472 | Some proof_bytes -> ( 1473 - match Cbor.decode_string Cbor.any proof_bytes with 1473 + match Cbor.of_string Cbor.any proof_bytes with 1474 1474 | Error _ -> Alcotest.fail "proof CBOR decode failed" 1475 1475 | Ok proof_cbor -> ( 1476 1476 match Cbor.Value.to_array proof_cbor with ··· 1641 1641 (* Innermost value: unsigned int 0 = 0x00 *) 1642 1642 Buffer.add_char buf '\x00'; 1643 1643 let data = Buffer.contents buf in 1644 - match Cbor.decode_string Cbor.any data with 1644 + match Cbor.of_string Cbor.any data with 1645 1645 | Ok _ -> Alcotest.fail "should reject deeply nested CBOR" 1646 1646 | Error _ -> () 1647 1647 ··· 1650 1650 rejected before allocating that many list cells. *) 1651 1651 (* Major 4 (array), additional 26 (4-byte length), then 0x10000000 = 268M *) 1652 1652 let header = "\x9a\x10\x00\x00\x00" in 1653 - match Cbor.decode_string Cbor.any header with 1653 + match Cbor.of_string Cbor.any header with 1654 1654 | Ok _ -> Alcotest.fail "should reject oversized array" 1655 1655 | Error _ -> () 1656 1656 ··· 1671 1671 (* Exported CBOR should contain all subjects *) 1672 1672 (* Exported should be non-empty and decodable *) 1673 1673 Alcotest.(check bool) "export non-empty" true (String.length exported > 0); 1674 - match Cbor.decode_string Cbor.any exported with 1674 + match Cbor.of_string Cbor.any exported with 1675 1675 | Error _ -> Alcotest.fail "export is not valid CBOR" 1676 1676 | Ok cbor -> ( 1677 1677 match Cbor.Value.to_map cbor with ··· 1697 1697 let _ = Scitt.vds_append vds ~key:"k1" ~value:"v1" in 1698 1698 let _ = Scitt.vds_append vds ~key:"k2" ~value:"v2" in 1699 1699 let exported = Scitt.vds_export vds in 1700 - match Cbor.decode_string Cbor.any exported with 1700 + match Cbor.of_string Cbor.any exported with 1701 1701 | Error _ -> Alcotest.fail "decode failed" 1702 1702 | Ok cbor -> ( 1703 1703 match Cbor.Value.to_map cbor with ··· 1745 1745 let test_import_missing_entries () = 1746 1746 (* An export blob with no "entries" field must be rejected. *) 1747 1747 let blob = 1748 - Cbor.encode_string Cbor.any 1748 + Cbor.to_string Cbor.any 1749 1749 (Cbor.Value.map 1750 1750 [ 1751 1751 (Cbor.Value.string "version", Cbor.Value.int 1); ··· 1763 1763 (* An entry that is not a [key, value] pair must be rejected, 1764 1764 not silently dropped. *) 1765 1765 let blob = 1766 - Cbor.encode_string Cbor.any 1766 + Cbor.to_string Cbor.any 1767 1767 (Cbor.Value.map 1768 1768 [ 1769 1769 (Cbor.Value.string "version", Cbor.Value.int 1); ··· 1792 1792 let _ = Scitt.vds_append vds ~key:"k2" ~value:"v2" in 1793 1793 let exported = Scitt.vds_export vds in 1794 1794 (* Parse, drop second entry, re-encode *) 1795 - match Cbor.decode_string Cbor.any exported with 1795 + match Cbor.of_string Cbor.any exported with 1796 1796 | Error _ -> Alcotest.fail "export decode failed" 1797 1797 | Ok cbor -> ( 1798 1798 match Cbor.Value.to_map cbor with ··· 1813 1813 pairs 1814 1814 in 1815 1815 let tampered_blob = 1816 - Cbor.encode_string Cbor.any (Cbor.Value.map tampered) 1816 + Cbor.to_string Cbor.any (Cbor.Value.map tampered) 1817 1817 in 1818 1818 (* Import rejects because root hash mismatch — the export includes 1819 1819 the original root, but replaying only 1 entry produces a different
+1 -1
test/test_vds.ml
··· 58 58 59 59 let test_import_rejects_bad_version () = 60 60 let bad = 61 - Cbor.encode_string Cbor.any 61 + Cbor.to_string Cbor.any 62 62 (Cbor.Value.map 63 63 [ 64 64 (Cbor.Value.string "version", Cbor.Value.int 99);