Content Security Policy header generation for OCaml

fix(lint): resolve E405, E410, E600 in ocaml-csp

- E405: add documentation for all CDN origin values
- E410: fix doc style for format_directive, strict_policy, default_policy
- E600: move Alcotest.run to test.ml, export suite from test_csp.ml

+38 -26
+22 -5
lib/csp.mli
··· 32 32 Pre-defined origins for popular CDNs. *) 33 33 34 34 val cdn_jsdelivr : string 35 + (** [cdn_jsdelivr] is ["https://cdn.jsdelivr.net"]. *) 36 + 35 37 val cdn_unpkg : string 38 + (** [cdn_unpkg] is ["https://unpkg.com"]. *) 39 + 36 40 val cdn_cdnjs : string 41 + (** [cdn_cdnjs] is ["https://cdnjs.cloudflare.com"]. *) 42 + 37 43 val cdn_google_fonts : string 44 + (** [cdn_google_fonts] is ["https://fonts.googleapis.com"]. *) 45 + 38 46 val cdn_google_static : string 47 + (** [cdn_google_static] is ["https://fonts.gstatic.com"]. *) 48 + 39 49 val cdn_google_apis : string 50 + (** [cdn_google_apis] is ["https://ajax.googleapis.com"]. *) 51 + 40 52 val cdn_cloudflare : string 53 + (** [cdn_cloudflare] is ["https://cdnjs.cloudflare.com"]. *) 54 + 41 55 val cdn_bootstrap : string 56 + (** [cdn_bootstrap] is ["https://stackpath.bootstrapcdn.com"]. *) 57 + 42 58 val cdn_fontawesome : string 59 + (** [cdn_fontawesome] is ["https://use.fontawesome.com"]. *) 43 60 44 61 val popular_cdns : string list 45 62 (** All popular CDN origins combined. *) ··· 62 79 ["'unsafe-inline'"], ["https://example.com"], or ["data:"]. *) 63 80 64 81 val format_directive : directive -> string 65 - (** Format a single directive as ["name value1 value2 ..."]. *) 82 + (** [format_directive d] formats [d] as ["name value1 value2 ..."]. *) 66 83 67 84 val format_policy : directive list -> string 68 85 (** Format a list of directives as a complete CSP policy string. *) ··· 70 87 (** {1 Preset Policies} *) 71 88 72 89 val strict_policy : string 73 - (** Strict CSP policy that blocks inline scripts and external resources. 90 + (** [strict_policy] blocks inline scripts and external resources. 74 91 75 92 - Scripts: ['self'] only (no inline, no CDNs) 76 93 - Styles: ['self'] only 77 94 - Images/Fonts: ['self'] + [data:] URIs 78 - - Blocks: eval, object-src, frame-ancestors *) 95 + - Blocks: eval, object-src, frame-ancestors. *) 79 96 80 97 val default_policy : string 81 - (** Default CSP policy balancing security and compatibility. 98 + (** [default_policy] balances security and compatibility. 82 99 83 100 - Scripts: ['self'] + ['unsafe-inline'] + popular CDNs 84 101 - Styles: ['self'] + ['unsafe-inline'] + popular CDNs 85 102 - Images/Fonts: ['self'] + [data:] + popular CDNs 86 - - Blocks: eval, object-src, frame-ancestors *) 103 + - Blocks: eval, object-src, frame-ancestors. *) 87 104 88 105 val strict_directives : directive list 89 106 (** The directives that make up {!strict_policy}. *)
+1 -1
test/dune
··· 1 1 (test 2 - (name test_csp) 2 + (name test) 3 3 (libraries csp alcotest))
+1
test/test.ml
··· 1 + let () = Alcotest.run "csp" [ Test_csp.suite ]
+11 -20
test/test_csp.ml
··· 83 83 Alcotest.(check string) "unpkg" "https://unpkg.com" Csp.cdn_unpkg; 84 84 Alcotest.(check int) "popular_cdns count" 9 (List.length Csp.popular_cdns) 85 85 86 - let () = 87 - Alcotest.run "csp" 86 + let suite = 87 + ( "csp", 88 88 [ 89 - ( "format", 90 - [ 91 - Alcotest.test_case "directive" `Quick test_format_directive; 92 - Alcotest.test_case "policy" `Quick test_format_policy; 93 - ] ); 94 - ( "presets", 95 - [ 96 - Alcotest.test_case "strict" `Quick test_strict_policy; 97 - Alcotest.test_case "default" `Quick test_default_policy; 98 - ] ); 99 - ( "header", 100 - [ 101 - Alcotest.test_case "header" `Quick test_header; 102 - Alcotest.test_case "header_value" `Quick test_header_value; 103 - Alcotest.test_case "custom" `Quick test_custom_header; 104 - ] ); 105 - ("cdn", [ Alcotest.test_case "constants" `Quick test_cdn_constants ]); 106 - ] 89 + Alcotest.test_case "directive" `Quick test_format_directive; 90 + Alcotest.test_case "policy" `Quick test_format_policy; 91 + Alcotest.test_case "strict" `Quick test_strict_policy; 92 + Alcotest.test_case "default" `Quick test_default_policy; 93 + Alcotest.test_case "header" `Quick test_header; 94 + Alcotest.test_case "header_value" `Quick test_header_value; 95 + Alcotest.test_case "custom" `Quick test_custom_header; 96 + Alcotest.test_case "constants" `Quick test_cdn_constants; 97 + ] )
+3
test/test_csp.mli
··· 1 + (** CSP header generation tests. *) 2 + 3 + val suite : string * unit Alcotest.test_case list