diff --git a/semgrep_output_v1.atd b/semgrep_output_v1.atd index 8b555220..2da55d04 100644 --- a/semgrep_output_v1.atd +++ b/semgrep_output_v1.atd @@ -1617,24 +1617,6 @@ type parsing_stats = { num_bytes: int; } -(* -Policy/automation related data the app wants the CLI to know about -certain findings. Right now this is only used for the app to cause -a CI scan to block, so 'kind' can only ever be "block". The list -of match_based_ids are the MIDs of the findings that the action -relates to. If a "block" action is present, the `app_block_override` -field should be true. - -This a record with a 'kind' field instead -instead of a sum type because ATD doesn't have convenient support for -adding new constructors to sum types without breaking backwards compatibility. -Right now we only have one kind of action ("block"), but in the future we may add more. -e.g. we could inform the CLI that a certain list of findings triggered a PR comment -*) -type app_finding_action = { - kind : string; - match_based_ids : string list; -} (* Response by the backend to the CLI to the POST /complete *) type ci_scan_complete_response = { @@ -1642,7 +1624,8 @@ type ci_scan_complete_response = { ~app_block_override: bool; (* only when app_block_override is true *) ~app_block_reason: string; - ~app_finding_actions : app_finding_action list; + (* match_based_ids of findings that semgrep-app determined should cause the scan to block *) + ~app_blocking_match_based_ids : string list; } (* ----------------------------- *) diff --git a/semgrep_output_v1.jsonschema b/semgrep_output_v1.jsonschema index 4597ef80..b38ea96e 100644 --- a/semgrep_output_v1.jsonschema +++ b/semgrep_output_v1.jsonschema @@ -1272,14 +1272,6 @@ "num_bytes": { "type": "integer" } } }, - "app_finding_action": { - "type": "object", - "required": [ "kind", "match_based_ids" ], - "properties": { - "kind": { "type": "string" }, - "match_based_ids": { "type": "array", "items": { "type": "string" } } - } - }, "ci_scan_complete_response": { "type": "object", "required": [ "success" ], @@ -1287,9 +1279,9 @@ "success": { "type": "boolean" }, "app_block_override": { "type": "boolean" }, "app_block_reason": { "type": "string" }, - "app_finding_actions": { + "app_blocking_match_based_ids": { "type": "array", - "items": { "$ref": "#/definitions/app_finding_action" } + "items": { "type": "string" } } } }, diff --git a/semgrep_output_v1.proto b/semgrep_output_v1.proto index ddc4aafb..62961ac7 100644 --- a/semgrep_output_v1.proto +++ b/semgrep_output_v1.proto @@ -1,6 +1,6 @@ // Generated by jsonschema2protobuf. DO NOT EDIT! // Source file: semgrep_output_v1.jsonschema -// Source file sha256 digest: 008531f03f4e1c824b6135bba8fe2285dc3c359d81113f1658e775aa664fb51f +// Source file sha256 digest: 5e8608ba9cbe8e79eb3cf5bd1d364fe08e3f22b332ba3215622b2bce91a6734f syntax = "proto3"; @@ -515,16 +515,11 @@ message ParsingStats { int64 num_bytes = 49709845; } -message AppFindingAction { - string kind = 3088172; - repeated string match_based_ids = 533667648; -} - message CiScanCompleteResponse { bool success = 224900935; bool app_block_override = 45266970; string app_block_reason = 276965897; - repeated AppFindingAction app_finding_actions = 91104740; + repeated string app_blocking_match_based_ids = 482968425; } message DependencyParserError { diff --git a/semgrep_output_v1.py b/semgrep_output_v1.py index 8acebad1..93ffe191 100644 --- a/semgrep_output_v1.py +++ b/semgrep_output_v1.py @@ -9083,37 +9083,6 @@ def to_json_string(self, **kw: Any) -> str: return json.dumps(self.to_json(), **kw) -@dataclass -class AppFindingAction: - """Original type: app_finding_action = { ... }""" - - kind: str - match_based_ids: List[str] - - @classmethod - def from_json(cls, x: Any) -> 'AppFindingAction': - if isinstance(x, dict): - return cls( - kind=_atd_read_string(x['kind']) if 'kind' in x else _atd_missing_json_field('AppFindingAction', 'kind'), - match_based_ids=_atd_read_list(_atd_read_string)(x['match_based_ids']) if 'match_based_ids' in x else _atd_missing_json_field('AppFindingAction', 'match_based_ids'), - ) - else: - _atd_bad_json('AppFindingAction', x) - - def to_json(self) -> Any: - res: Dict[str, Any] = {} - res['kind'] = _atd_write_string(self.kind) - res['match_based_ids'] = _atd_write_list(_atd_write_string)(self.match_based_ids) - return res - - @classmethod - def from_json_string(cls, x: str) -> 'AppFindingAction': - return cls.from_json(json.loads(x)) - - def to_json_string(self, **kw: Any) -> str: - return json.dumps(self.to_json(), **kw) - - @dataclass class CiScanCompleteResponse: """Original type: ci_scan_complete_response = { ... }""" @@ -9121,7 +9090,7 @@ class CiScanCompleteResponse: success: bool app_block_override: bool = field(default_factory=lambda: False) app_block_reason: str = field(default_factory=lambda: "") - app_finding_actions: List[AppFindingAction] = field(default_factory=lambda: []) + app_blocking_match_based_ids: List[str] = field(default_factory=lambda: []) @classmethod def from_json(cls, x: Any) -> 'CiScanCompleteResponse': @@ -9130,7 +9099,7 @@ def from_json(cls, x: Any) -> 'CiScanCompleteResponse': success=_atd_read_bool(x['success']) if 'success' in x else _atd_missing_json_field('CiScanCompleteResponse', 'success'), app_block_override=_atd_read_bool(x['app_block_override']) if 'app_block_override' in x else False, app_block_reason=_atd_read_string(x['app_block_reason']) if 'app_block_reason' in x else "", - app_finding_actions=_atd_read_list(AppFindingAction.from_json)(x['app_finding_actions']) if 'app_finding_actions' in x else [], + app_blocking_match_based_ids=_atd_read_list(_atd_read_string)(x['app_blocking_match_based_ids']) if 'app_blocking_match_based_ids' in x else [], ) else: _atd_bad_json('CiScanCompleteResponse', x) @@ -9140,7 +9109,7 @@ def to_json(self) -> Any: res['success'] = _atd_write_bool(self.success) res['app_block_override'] = _atd_write_bool(self.app_block_override) res['app_block_reason'] = _atd_write_string(self.app_block_reason) - res['app_finding_actions'] = _atd_write_list((lambda x: x.to_json()))(self.app_finding_actions) + res['app_blocking_match_based_ids'] = _atd_write_list(_atd_write_string)(self.app_blocking_match_based_ids) return res @classmethod diff --git a/semgrep_output_v1.ts b/semgrep_output_v1.ts index 3a2de107..bd76b09c 100644 --- a/semgrep_output_v1.ts +++ b/semgrep_output_v1.ts @@ -696,16 +696,11 @@ export type ParsingStats = { num_bytes: number /*int*/; } -export type AppFindingAction = { - kind: string; - match_based_ids: string[]; -} - export type CiScanCompleteResponse = { success: boolean; app_block_override: boolean; app_block_reason: string; - app_finding_actions: AppFindingAction[]; + app_blocking_match_based_ids: string[]; } export type CiScanDependencies = Map @@ -3114,26 +3109,12 @@ export function readParsingStats(x: any, context: any = x): ParsingStats { }; } -export function writeAppFindingAction(x: AppFindingAction, context: any = x): any { - return { - 'kind': _atd_write_required_field('AppFindingAction', 'kind', _atd_write_string, x.kind, x), - 'match_based_ids': _atd_write_required_field('AppFindingAction', 'match_based_ids', _atd_write_array(_atd_write_string), x.match_based_ids, x), - }; -} - -export function readAppFindingAction(x: any, context: any = x): AppFindingAction { - return { - kind: _atd_read_required_field('AppFindingAction', 'kind', _atd_read_string, x['kind'], x), - match_based_ids: _atd_read_required_field('AppFindingAction', 'match_based_ids', _atd_read_array(_atd_read_string), x['match_based_ids'], x), - }; -} - export function writeCiScanCompleteResponse(x: CiScanCompleteResponse, context: any = x): any { return { 'success': _atd_write_required_field('CiScanCompleteResponse', 'success', _atd_write_bool, x.success, x), 'app_block_override': _atd_write_field_with_default(_atd_write_bool, false, x.app_block_override, x), 'app_block_reason': _atd_write_field_with_default(_atd_write_string, "", x.app_block_reason, x), - 'app_finding_actions': _atd_write_field_with_default(_atd_write_array(writeAppFindingAction), [], x.app_finding_actions, x), + 'app_blocking_match_based_ids': _atd_write_field_with_default(_atd_write_array(_atd_write_string), [], x.app_blocking_match_based_ids, x), }; } @@ -3142,7 +3123,7 @@ export function readCiScanCompleteResponse(x: any, context: any = x): CiScanComp success: _atd_read_required_field('CiScanCompleteResponse', 'success', _atd_read_bool, x['success'], x), app_block_override: _atd_read_field_with_default(_atd_read_bool, false, x['app_block_override'], x), app_block_reason: _atd_read_field_with_default(_atd_read_string, "", x['app_block_reason'], x), - app_finding_actions: _atd_read_field_with_default(_atd_read_array(readAppFindingAction), [], x['app_finding_actions'], x), + app_blocking_match_based_ids: _atd_read_field_with_default(_atd_read_array(_atd_read_string), [], x['app_blocking_match_based_ids'], x), }; } diff --git a/semgrep_output_v1_j.ml b/semgrep_output_v1_j.ml index 3937f7a5..497198b3 100644 --- a/semgrep_output_v1_j.ml +++ b/semgrep_output_v1_j.ml @@ -877,17 +877,12 @@ type ci_scan_results_response = } [@@deriving show] -type app_finding_action = Semgrep_output_v1_t.app_finding_action = { - kind: string; - match_based_ids: string list -} - type ci_scan_complete_response = Semgrep_output_v1_t.ci_scan_complete_response = { success: bool; app_block_override: bool; app_block_reason: string; - app_finding_actions: app_finding_action list + app_blocking_match_based_ids: string list } [@@deriving show] @@ -34577,175 +34572,6 @@ let read_ci_scan_results_response = ( ) let ci_scan_results_response_of_string s = read_ci_scan_results_response (Yojson.Safe.init_lexer ()) (Lexing.from_string s) -let write_app_finding_action : _ -> app_finding_action -> _ = ( - fun ob (x : app_finding_action) -> - Buffer.add_char ob '{'; - let is_first = ref true in - if !is_first then - is_first := false - else - Buffer.add_char ob ','; - Buffer.add_string ob "\"kind\":"; - ( - Yojson.Safe.write_string - ) - ob x.kind; - if !is_first then - is_first := false - else - Buffer.add_char ob ','; - Buffer.add_string ob "\"match_based_ids\":"; - ( - write__string_list - ) - ob x.match_based_ids; - Buffer.add_char ob '}'; -) -let string_of_app_finding_action ?(len = 1024) x = - let ob = Buffer.create len in - write_app_finding_action ob x; - Buffer.contents ob -let read_app_finding_action = ( - fun p lb -> - Yojson.Safe.read_space p lb; - Yojson.Safe.read_lcurl p lb; - let field_kind = ref (None) in - let field_match_based_ids = ref (None) in - try - Yojson.Safe.read_space p lb; - Yojson.Safe.read_object_end lb; - Yojson.Safe.read_space p lb; - let f = - fun s pos len -> - if pos < 0 || len < 0 || pos + len > String.length s then - invalid_arg (Printf.sprintf "out-of-bounds substring position or length: string = %S, requested position = %i, requested length = %i" s pos len); - match len with - | 4 -> ( - if String.unsafe_get s pos = 'k' && String.unsafe_get s (pos+1) = 'i' && String.unsafe_get s (pos+2) = 'n' && String.unsafe_get s (pos+3) = 'd' then ( - 0 - ) - else ( - -1 - ) - ) - | 15 -> ( - if String.unsafe_get s pos = 'm' && String.unsafe_get s (pos+1) = 'a' && String.unsafe_get s (pos+2) = 't' && String.unsafe_get s (pos+3) = 'c' && String.unsafe_get s (pos+4) = 'h' && String.unsafe_get s (pos+5) = '_' && String.unsafe_get s (pos+6) = 'b' && String.unsafe_get s (pos+7) = 'a' && String.unsafe_get s (pos+8) = 's' && String.unsafe_get s (pos+9) = 'e' && String.unsafe_get s (pos+10) = 'd' && String.unsafe_get s (pos+11) = '_' && String.unsafe_get s (pos+12) = 'i' && String.unsafe_get s (pos+13) = 'd' && String.unsafe_get s (pos+14) = 's' then ( - 1 - ) - else ( - -1 - ) - ) - | _ -> ( - -1 - ) - in - let i = Yojson.Safe.map_ident p f lb in - Atdgen_runtime.Oj_run.read_until_field_value p lb; - ( - match i with - | 0 -> - field_kind := ( - Some ( - ( - Atdgen_runtime.Oj_run.read_string - ) p lb - ) - ); - | 1 -> - field_match_based_ids := ( - Some ( - ( - read__string_list - ) p lb - ) - ); - | _ -> ( - Yojson.Safe.skip_json p lb - ) - ); - while true do - Yojson.Safe.read_space p lb; - Yojson.Safe.read_object_sep p lb; - Yojson.Safe.read_space p lb; - let f = - fun s pos len -> - if pos < 0 || len < 0 || pos + len > String.length s then - invalid_arg (Printf.sprintf "out-of-bounds substring position or length: string = %S, requested position = %i, requested length = %i" s pos len); - match len with - | 4 -> ( - if String.unsafe_get s pos = 'k' && String.unsafe_get s (pos+1) = 'i' && String.unsafe_get s (pos+2) = 'n' && String.unsafe_get s (pos+3) = 'd' then ( - 0 - ) - else ( - -1 - ) - ) - | 15 -> ( - if String.unsafe_get s pos = 'm' && String.unsafe_get s (pos+1) = 'a' && String.unsafe_get s (pos+2) = 't' && String.unsafe_get s (pos+3) = 'c' && String.unsafe_get s (pos+4) = 'h' && String.unsafe_get s (pos+5) = '_' && String.unsafe_get s (pos+6) = 'b' && String.unsafe_get s (pos+7) = 'a' && String.unsafe_get s (pos+8) = 's' && String.unsafe_get s (pos+9) = 'e' && String.unsafe_get s (pos+10) = 'd' && String.unsafe_get s (pos+11) = '_' && String.unsafe_get s (pos+12) = 'i' && String.unsafe_get s (pos+13) = 'd' && String.unsafe_get s (pos+14) = 's' then ( - 1 - ) - else ( - -1 - ) - ) - | _ -> ( - -1 - ) - in - let i = Yojson.Safe.map_ident p f lb in - Atdgen_runtime.Oj_run.read_until_field_value p lb; - ( - match i with - | 0 -> - field_kind := ( - Some ( - ( - Atdgen_runtime.Oj_run.read_string - ) p lb - ) - ); - | 1 -> - field_match_based_ids := ( - Some ( - ( - read__string_list - ) p lb - ) - ); - | _ -> ( - Yojson.Safe.skip_json p lb - ) - ); - done; - assert false; - with Yojson.End_of_object -> ( - ( - { - kind = (match !field_kind with Some x -> x | None -> Atdgen_runtime.Oj_run.missing_field p "kind"); - match_based_ids = (match !field_match_based_ids with Some x -> x | None -> Atdgen_runtime.Oj_run.missing_field p "match_based_ids"); - } - : app_finding_action) - ) -) -let app_finding_action_of_string s = - read_app_finding_action (Yojson.Safe.init_lexer ()) (Lexing.from_string s) -let write__app_finding_action_list = ( - Atdgen_runtime.Oj_run.write_list ( - write_app_finding_action - ) -) -let string_of__app_finding_action_list ?(len = 1024) x = - let ob = Buffer.create len in - write__app_finding_action_list ob x; - Buffer.contents ob -let read__app_finding_action_list = ( - Atdgen_runtime.Oj_run.read_list ( - read_app_finding_action - ) -) -let _app_finding_action_list_of_string s = - read__app_finding_action_list (Yojson.Safe.init_lexer ()) (Lexing.from_string s) let write_ci_scan_complete_response : _ -> ci_scan_complete_response -> _ = ( fun ob (x : ci_scan_complete_response) -> Buffer.add_char ob '{'; @@ -34781,11 +34607,11 @@ let write_ci_scan_complete_response : _ -> ci_scan_complete_response -> _ = ( is_first := false else Buffer.add_char ob ','; - Buffer.add_string ob "\"app_finding_actions\":"; + Buffer.add_string ob "\"app_blocking_match_based_ids\":"; ( - write__app_finding_action_list + write__string_list ) - ob x.app_finding_actions; + ob x.app_blocking_match_based_ids; Buffer.add_char ob '}'; ) let string_of_ci_scan_complete_response ?(len = 1024) x = @@ -34799,7 +34625,7 @@ let read_ci_scan_complete_response = ( let field_success = ref (None) in let field_app_block_override = ref (false) in let field_app_block_reason = ref ("") in - let field_app_finding_actions = ref ([]) in + let field_app_blocking_match_based_ids = ref ([]) in try Yojson.Safe.read_space p lb; Yojson.Safe.read_object_end lb; @@ -34833,8 +34659,8 @@ let read_ci_scan_complete_response = ( -1 ) ) - | 19 -> ( - if String.unsafe_get s pos = 'a' && String.unsafe_get s (pos+1) = 'p' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = '_' && String.unsafe_get s (pos+4) = 'f' && String.unsafe_get s (pos+5) = 'i' && String.unsafe_get s (pos+6) = 'n' && String.unsafe_get s (pos+7) = 'd' && String.unsafe_get s (pos+8) = 'i' && String.unsafe_get s (pos+9) = 'n' && String.unsafe_get s (pos+10) = 'g' && String.unsafe_get s (pos+11) = '_' && String.unsafe_get s (pos+12) = 'a' && String.unsafe_get s (pos+13) = 'c' && String.unsafe_get s (pos+14) = 't' && String.unsafe_get s (pos+15) = 'i' && String.unsafe_get s (pos+16) = 'o' && String.unsafe_get s (pos+17) = 'n' && String.unsafe_get s (pos+18) = 's' then ( + | 28 -> ( + if String.unsafe_get s pos = 'a' && String.unsafe_get s (pos+1) = 'p' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = '_' && String.unsafe_get s (pos+4) = 'b' && String.unsafe_get s (pos+5) = 'l' && String.unsafe_get s (pos+6) = 'o' && String.unsafe_get s (pos+7) = 'c' && String.unsafe_get s (pos+8) = 'k' && String.unsafe_get s (pos+9) = 'i' && String.unsafe_get s (pos+10) = 'n' && String.unsafe_get s (pos+11) = 'g' && String.unsafe_get s (pos+12) = '_' && String.unsafe_get s (pos+13) = 'm' && String.unsafe_get s (pos+14) = 'a' && String.unsafe_get s (pos+15) = 't' && String.unsafe_get s (pos+16) = 'c' && String.unsafe_get s (pos+17) = 'h' && String.unsafe_get s (pos+18) = '_' && String.unsafe_get s (pos+19) = 'b' && String.unsafe_get s (pos+20) = 'a' && String.unsafe_get s (pos+21) = 's' && String.unsafe_get s (pos+22) = 'e' && String.unsafe_get s (pos+23) = 'd' && String.unsafe_get s (pos+24) = '_' && String.unsafe_get s (pos+25) = 'i' && String.unsafe_get s (pos+26) = 'd' && String.unsafe_get s (pos+27) = 's' then ( 3 ) else ( @@ -34875,9 +34701,9 @@ let read_ci_scan_complete_response = ( ) | 3 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( - field_app_finding_actions := ( + field_app_blocking_match_based_ids := ( ( - read__app_finding_action_list + read__string_list ) p lb ); ) @@ -34918,8 +34744,8 @@ let read_ci_scan_complete_response = ( -1 ) ) - | 19 -> ( - if String.unsafe_get s pos = 'a' && String.unsafe_get s (pos+1) = 'p' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = '_' && String.unsafe_get s (pos+4) = 'f' && String.unsafe_get s (pos+5) = 'i' && String.unsafe_get s (pos+6) = 'n' && String.unsafe_get s (pos+7) = 'd' && String.unsafe_get s (pos+8) = 'i' && String.unsafe_get s (pos+9) = 'n' && String.unsafe_get s (pos+10) = 'g' && String.unsafe_get s (pos+11) = '_' && String.unsafe_get s (pos+12) = 'a' && String.unsafe_get s (pos+13) = 'c' && String.unsafe_get s (pos+14) = 't' && String.unsafe_get s (pos+15) = 'i' && String.unsafe_get s (pos+16) = 'o' && String.unsafe_get s (pos+17) = 'n' && String.unsafe_get s (pos+18) = 's' then ( + | 28 -> ( + if String.unsafe_get s pos = 'a' && String.unsafe_get s (pos+1) = 'p' && String.unsafe_get s (pos+2) = 'p' && String.unsafe_get s (pos+3) = '_' && String.unsafe_get s (pos+4) = 'b' && String.unsafe_get s (pos+5) = 'l' && String.unsafe_get s (pos+6) = 'o' && String.unsafe_get s (pos+7) = 'c' && String.unsafe_get s (pos+8) = 'k' && String.unsafe_get s (pos+9) = 'i' && String.unsafe_get s (pos+10) = 'n' && String.unsafe_get s (pos+11) = 'g' && String.unsafe_get s (pos+12) = '_' && String.unsafe_get s (pos+13) = 'm' && String.unsafe_get s (pos+14) = 'a' && String.unsafe_get s (pos+15) = 't' && String.unsafe_get s (pos+16) = 'c' && String.unsafe_get s (pos+17) = 'h' && String.unsafe_get s (pos+18) = '_' && String.unsafe_get s (pos+19) = 'b' && String.unsafe_get s (pos+20) = 'a' && String.unsafe_get s (pos+21) = 's' && String.unsafe_get s (pos+22) = 'e' && String.unsafe_get s (pos+23) = 'd' && String.unsafe_get s (pos+24) = '_' && String.unsafe_get s (pos+25) = 'i' && String.unsafe_get s (pos+26) = 'd' && String.unsafe_get s (pos+27) = 's' then ( 3 ) else ( @@ -34960,9 +34786,9 @@ let read_ci_scan_complete_response = ( ) | 3 -> if not (Yojson.Safe.read_null_if_possible p lb) then ( - field_app_finding_actions := ( + field_app_blocking_match_based_ids := ( ( - read__app_finding_action_list + read__string_list ) p lb ); ) @@ -34978,7 +34804,7 @@ let read_ci_scan_complete_response = ( success = (match !field_success with Some x -> x | None -> Atdgen_runtime.Oj_run.missing_field p "success"); app_block_override = !field_app_block_override; app_block_reason = !field_app_block_reason; - app_finding_actions = !field_app_finding_actions; + app_blocking_match_based_ids = !field_app_blocking_match_based_ids; } : ci_scan_complete_response) ) diff --git a/semgrep_output_v1_j.mli b/semgrep_output_v1_j.mli index ec940f5f..7692c360 100644 --- a/semgrep_output_v1_j.mli +++ b/semgrep_output_v1_j.mli @@ -877,17 +877,12 @@ type ci_scan_results_response = } [@@deriving show] -type app_finding_action = Semgrep_output_v1_t.app_finding_action = { - kind: string; - match_based_ids: string list -} - type ci_scan_complete_response = Semgrep_output_v1_t.ci_scan_complete_response = { success: bool; app_block_override: bool; app_block_reason: string; - app_finding_actions: app_finding_action list + app_blocking_match_based_ids: string list } [@@deriving show] @@ -3651,26 +3646,6 @@ val ci_scan_results_response_of_string : string -> ci_scan_results_response (** Deserialize JSON data of type {!type:ci_scan_results_response}. *) -val write_app_finding_action : - Buffer.t -> app_finding_action -> unit - (** Output a JSON value of type {!type:app_finding_action}. *) - -val string_of_app_finding_action : - ?len:int -> app_finding_action -> string - (** Serialize a value of type {!type:app_finding_action} - into a JSON string. - @param len specifies the initial length - of the buffer used internally. - Default: 1024. *) - -val read_app_finding_action : - Yojson.Safe.lexer_state -> Lexing.lexbuf -> app_finding_action - (** Input JSON data of type {!type:app_finding_action}. *) - -val app_finding_action_of_string : - string -> app_finding_action - (** Deserialize JSON data of type {!type:app_finding_action}. *) - val write_ci_scan_complete_response : Buffer.t -> ci_scan_complete_response -> unit (** Output a JSON value of type {!type:ci_scan_complete_response}. *)