diff --git a/python/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.py b/python/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.py index d7109cf2f..eb347e47a 100644 --- a/python/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.py +++ b/python/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.py @@ -20,7 +20,7 @@ from sift.rules.v1 import rules_pb2 as sift_dot_rules_dot_v1_dot_rules__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n-sift/rule_evaluation/v1/rule_evaluation.proto\x12\x17sift.rule_evaluation.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a-sift/common/type/v1/resource_identifier.proto\x1a\x19sift/rules/v1/rules.proto\"\xe2\x05\n\x14\x45valuateRulesRequest\x12;\n\x03run\x18\x01 \x01(\x0b\x32\'.sift.common.type.v1.ResourceIdentifierH\x00R\x03run\x12\x42\n\x06\x61ssets\x18\x02 \x01(\x0b\x32(.sift.rule_evaluation.v1.AssetsTimeRangeH\x00R\x06\x61ssets\x12M\n\x0erun_time_range\x18\t \x01(\x0b\x32%.sift.rule_evaluation.v1.RunTimeRangeH\x00R\x0crunTimeRange\x12U\n\x05rules\x18\x03 \x01(\x0b\x32=.sift.rule_evaluation.v1.EvaluateRulesFromCurrentRuleVersionsH\x01R\x05rules\x12]\n\rrule_versions\x18\x04 \x01(\x0b\x32\x36.sift.rule_evaluation.v1.EvaluateRulesFromRuleVersionsH\x01R\x0cruleVersions\x12\x63\n\x0freport_template\x18\x05 \x01(\x0b\x32\x38.sift.rule_evaluation.v1.EvaluateRulesFromReportTemplateH\x01R\x0ereportTemplate\x12\x66\n\x12\x61nnotation_options\x18\x06 \x01(\x0b\x32\x37.sift.rule_evaluation.v1.EvaluateRulesAnnotationOptionsR\x11\x61nnotationOptions\x12,\n\x0forganization_id\x18\x07 \x01(\tB\x03\xe0\x41\x01R\x0eorganizationId\x12)\n\x0breport_name\x18\x08 \x01(\tB\x03\xe0\x41\x01H\x02R\nreportName\x88\x01\x01\x42\x06\n\x04timeB\x06\n\x04modeB\x0e\n\x0c_report_name\"\xeb\x01\n\x0cRunTimeRange\x12\x39\n\x03run\x18\x01 \x01(\x0b\x32\'.sift.common.type.v1.ResourceIdentifierR\x03run\x12\x43\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x01H\x00R\tstartTime\x88\x01\x01\x12?\n\x08\x65nd_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x01H\x01R\x07\x65ndTime\x88\x01\x01\x42\r\n\x0b_start_timeB\x0b\n\t_end_time\"\xcf\x01\n\x0f\x41ssetsTimeRange\x12@\n\x06\x61ssets\x18\x01 \x01(\x0b\x32#.sift.common.type.v1.NamedResourcesB\x03\xe0\x41\x02R\x06\x61ssets\x12>\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\tstartTime\x12:\n\x08\x65nd_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x07\x65ndTime\"k\n$EvaluateRulesFromCurrentRuleVersions\x12\x43\n\x05rules\x18\x01 \x01(\x0b\x32(.sift.common.type.v1.ResourceIdentifiersB\x03\xe0\x41\x02R\x05rules\"x\n\x1f\x45valuateRulesFromReportTemplate\x12U\n\x0freport_template\x18\x01 \x01(\x0b\x32\'.sift.common.type.v1.ResourceIdentifierB\x03\xe0\x41\x02R\x0ereportTemplate\"N\n\x1d\x45valuateRulesFromRuleVersions\x12-\n\x10rule_version_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x0eruleVersionIds\"^\n\x1e\x45valuateRulesAnnotationOptions\x12<\n\x04tags\x18\x01 \x01(\x0b\x32#.sift.common.type.v1.NamedResourcesB\x03\xe0\x41\x02R\x04tags\"\xb7\x01\n\x15\x45valuateRulesResponse\x12=\n\x18\x63reated_annotation_count\x18\x01 \x01(\x05\x42\x03\xe0\x41\x02R\x16\x63reatedAnnotationCount\x12%\n\treport_id\x18\x02 \x01(\tB\x03\xe0\x41\x01H\x00R\x08reportId\x88\x01\x01\x12\x1f\n\x06job_id\x18\x03 \x01(\tB\x03\xe0\x41\x01H\x01R\x05jobId\x88\x01\x01\x42\x0c\n\n_report_idB\t\n\x07_job_id\"\xde\x04\n\x1b\x45valuateRulesPreviewRequest\x12;\n\x03run\x18\x01 \x01(\x0b\x32\'.sift.common.type.v1.ResourceIdentifierH\x00R\x03run\x12M\n\x0erun_time_range\x18\x08 \x01(\x0b\x32%.sift.rule_evaluation.v1.RunTimeRangeH\x00R\x0crunTimeRange\x12U\n\x05rules\x18\x03 \x01(\x0b\x32=.sift.rule_evaluation.v1.EvaluateRulesFromCurrentRuleVersionsH\x01R\x05rules\x12]\n\rrule_versions\x18\x04 \x01(\x0b\x32\x36.sift.rule_evaluation.v1.EvaluateRulesFromRuleVersionsH\x01R\x0cruleVersions\x12\x63\n\x0freport_template\x18\x05 \x01(\x0b\x32\x38.sift.rule_evaluation.v1.EvaluateRulesFromReportTemplateH\x01R\x0ereportTemplate\x12Z\n\x0crule_configs\x18\x06 \x01(\x0b\x32\x35.sift.rule_evaluation.v1.EvaluateRulesFromRuleConfigsH\x01R\x0bruleConfigs\x12,\n\x0forganization_id\x18\x07 \x01(\tB\x03\xe0\x41\x01R\x0eorganizationIdB\x06\n\x04timeB\x06\n\x04mode\"_\n\x1c\x45valuateRulesFromRuleConfigs\x12?\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32 .sift.rules.v1.UpdateRuleRequestB\x03\xe0\x41\x02R\x07\x63onfigs\"\xe8\x01\n\x11RulePreviewOutput\x12 \n\trule_name\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x08ruleName\x12\x17\n\x07rule_id\x18\x02 \x01(\tR\x06ruleId\x12&\n\x0frule_version_id\x18\x03 \x01(\tR\rruleVersionId\x12\x1e\n\x08\x61sset_id\x18\x04 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\x12 \n\texit_code\x18\x05 \x01(\x05\x42\x03\xe0\x41\x02R\x08\x65xitCode\x12\x16\n\x06stdout\x18\x06 \x01(\tR\x06stdout\x12\x16\n\x06stderr\x18\x07 \x01(\tR\x06stderr\"\xfd\x01\n\x1c\x45valuateRulesPreviewResponse\x12=\n\x18\x63reated_annotation_count\x18\x01 \x01(\x05\x42\x03\xe0\x41\x02R\x16\x63reatedAnnotationCount\x12O\n\x13\x64ry_run_annotations\x18\x02 \x03(\x0b\x32\x1f.sift.rules.v1.DryRunAnnotationR\x11\x64ryRunAnnotations\x12M\n\x0crule_outputs\x18\x03 \x03(\x0b\x32*.sift.rule_evaluation.v1.RulePreviewOutputR\x0bruleOutputs2\xd8\x06\n\x15RuleEvaluationService\x12\xc3\x02\n\rEvaluateRules\x12-.sift.rule_evaluation.v1.EvaluateRulesRequest\x1a..sift.rule_evaluation.v1.EvaluateRulesResponse\"\xd2\x01\x92\x41\xa7\x01\x12\rEvaluateRules\x1a\x95\x01\x45valuate rules from a designated source against a run or asset and return the total amount of annotations created and the ID of the generated report.\x82\xd3\xe4\x93\x02!\"\x1c/api/v1/rules/evaluate-rules:\x01*\x12\xda\x02\n\x14\x45valuateRulesPreview\x12\x34.sift.rule_evaluation.v1.EvaluateRulesPreviewRequest\x1a\x35.sift.rule_evaluation.v1.EvaluateRulesPreviewResponse\"\xd4\x01\x92\x41\xa1\x01\x12\x14\x45valuateRulesPreview\x1a\x88\x01Perform a dry run evaluation for existing rules or rule configurations against a run and return the annotations that would be generated.\x82\xd3\xe4\x93\x02)\"$/api/v1/rules/evaluate-rules:preview:\x01*\x1a\x9b\x01\x92\x41\x97\x01\x12\x1aService to evaluate rules.\x1ay\n\x1fRead more about what rules are.\x12Vhttps://customer.support.siftstack.com/servicedesk/customer/portal/2/article/265421102B\xca\x01\n\x1b\x63om.sift.rule_evaluation.v1B\x13RuleEvaluationProtoP\x01\xa2\x02\x03SRX\xaa\x02\x16Sift.RuleEvaluation.V1\xca\x02\x16Sift\\RuleEvaluation\\V1\xe2\x02\"Sift\\RuleEvaluation\\V1\\GPBMetadata\xea\x02\x18Sift::RuleEvaluation::V1\x92\x41\x1b\x12\x19\n\x17Rule Evaluation Serviceb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n-sift/rule_evaluation/v1/rule_evaluation.proto\x12\x17sift.rule_evaluation.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a-sift/common/type/v1/resource_identifier.proto\x1a\x19sift/rules/v1/rules.proto\"\x96\x06\n\x14\x45valuateRulesRequest\x12;\n\x03run\x18\x01 \x01(\x0b\x32\'.sift.common.type.v1.ResourceIdentifierH\x00R\x03run\x12\x42\n\x06\x61ssets\x18\x02 \x01(\x0b\x32(.sift.rule_evaluation.v1.AssetsTimeRangeH\x00R\x06\x61ssets\x12M\n\x0erun_time_range\x18\t \x01(\x0b\x32%.sift.rule_evaluation.v1.RunTimeRangeH\x00R\x0crunTimeRange\x12U\n\x05rules\x18\x03 \x01(\x0b\x32=.sift.rule_evaluation.v1.EvaluateRulesFromCurrentRuleVersionsH\x01R\x05rules\x12]\n\rrule_versions\x18\x04 \x01(\x0b\x32\x36.sift.rule_evaluation.v1.EvaluateRulesFromRuleVersionsH\x01R\x0cruleVersions\x12\x63\n\x0freport_template\x18\x05 \x01(\x0b\x32\x38.sift.rule_evaluation.v1.EvaluateRulesFromReportTemplateH\x01R\x0ereportTemplate\x12\x32\n\x14\x61ll_applicable_rules\x18\n \x01(\x08H\x01R\x12\x61llApplicableRules\x12\x66\n\x12\x61nnotation_options\x18\x06 \x01(\x0b\x32\x37.sift.rule_evaluation.v1.EvaluateRulesAnnotationOptionsR\x11\x61nnotationOptions\x12,\n\x0forganization_id\x18\x07 \x01(\tB\x03\xe0\x41\x01R\x0eorganizationId\x12)\n\x0breport_name\x18\x08 \x01(\tB\x03\xe0\x41\x01H\x02R\nreportName\x88\x01\x01\x42\x06\n\x04timeB\x06\n\x04modeB\x0e\n\x0c_report_name\"\xeb\x01\n\x0cRunTimeRange\x12\x39\n\x03run\x18\x01 \x01(\x0b\x32\'.sift.common.type.v1.ResourceIdentifierR\x03run\x12\x43\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x01H\x00R\tstartTime\x88\x01\x01\x12?\n\x08\x65nd_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x01H\x01R\x07\x65ndTime\x88\x01\x01\x42\r\n\x0b_start_timeB\x0b\n\t_end_time\"\xcf\x01\n\x0f\x41ssetsTimeRange\x12@\n\x06\x61ssets\x18\x01 \x01(\x0b\x32#.sift.common.type.v1.NamedResourcesB\x03\xe0\x41\x02R\x06\x61ssets\x12>\n\nstart_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\tstartTime\x12:\n\x08\x65nd_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x07\x65ndTime\"k\n$EvaluateRulesFromCurrentRuleVersions\x12\x43\n\x05rules\x18\x01 \x01(\x0b\x32(.sift.common.type.v1.ResourceIdentifiersB\x03\xe0\x41\x02R\x05rules\"x\n\x1f\x45valuateRulesFromReportTemplate\x12U\n\x0freport_template\x18\x01 \x01(\x0b\x32\'.sift.common.type.v1.ResourceIdentifierB\x03\xe0\x41\x02R\x0ereportTemplate\"N\n\x1d\x45valuateRulesFromRuleVersions\x12-\n\x10rule_version_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x0eruleVersionIds\"^\n\x1e\x45valuateRulesAnnotationOptions\x12<\n\x04tags\x18\x01 \x01(\x0b\x32#.sift.common.type.v1.NamedResourcesB\x03\xe0\x41\x02R\x04tags\"\xb7\x01\n\x15\x45valuateRulesResponse\x12=\n\x18\x63reated_annotation_count\x18\x01 \x01(\x05\x42\x03\xe0\x41\x02R\x16\x63reatedAnnotationCount\x12%\n\treport_id\x18\x02 \x01(\tB\x03\xe0\x41\x01H\x00R\x08reportId\x88\x01\x01\x12\x1f\n\x06job_id\x18\x03 \x01(\tB\x03\xe0\x41\x01H\x01R\x05jobId\x88\x01\x01\x42\x0c\n\n_report_idB\t\n\x07_job_id\"\xde\x04\n\x1b\x45valuateRulesPreviewRequest\x12;\n\x03run\x18\x01 \x01(\x0b\x32\'.sift.common.type.v1.ResourceIdentifierH\x00R\x03run\x12M\n\x0erun_time_range\x18\x08 \x01(\x0b\x32%.sift.rule_evaluation.v1.RunTimeRangeH\x00R\x0crunTimeRange\x12U\n\x05rules\x18\x03 \x01(\x0b\x32=.sift.rule_evaluation.v1.EvaluateRulesFromCurrentRuleVersionsH\x01R\x05rules\x12]\n\rrule_versions\x18\x04 \x01(\x0b\x32\x36.sift.rule_evaluation.v1.EvaluateRulesFromRuleVersionsH\x01R\x0cruleVersions\x12\x63\n\x0freport_template\x18\x05 \x01(\x0b\x32\x38.sift.rule_evaluation.v1.EvaluateRulesFromReportTemplateH\x01R\x0ereportTemplate\x12Z\n\x0crule_configs\x18\x06 \x01(\x0b\x32\x35.sift.rule_evaluation.v1.EvaluateRulesFromRuleConfigsH\x01R\x0bruleConfigs\x12,\n\x0forganization_id\x18\x07 \x01(\tB\x03\xe0\x41\x01R\x0eorganizationIdB\x06\n\x04timeB\x06\n\x04mode\"_\n\x1c\x45valuateRulesFromRuleConfigs\x12?\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32 .sift.rules.v1.UpdateRuleRequestB\x03\xe0\x41\x02R\x07\x63onfigs\"\xe8\x01\n\x11RulePreviewOutput\x12 \n\trule_name\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x08ruleName\x12\x17\n\x07rule_id\x18\x02 \x01(\tR\x06ruleId\x12&\n\x0frule_version_id\x18\x03 \x01(\tR\rruleVersionId\x12\x1e\n\x08\x61sset_id\x18\x04 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\x12 \n\texit_code\x18\x05 \x01(\x05\x42\x03\xe0\x41\x02R\x08\x65xitCode\x12\x16\n\x06stdout\x18\x06 \x01(\tR\x06stdout\x12\x16\n\x06stderr\x18\x07 \x01(\tR\x06stderr\"\xfd\x01\n\x1c\x45valuateRulesPreviewResponse\x12=\n\x18\x63reated_annotation_count\x18\x01 \x01(\x05\x42\x03\xe0\x41\x02R\x16\x63reatedAnnotationCount\x12O\n\x13\x64ry_run_annotations\x18\x02 \x03(\x0b\x32\x1f.sift.rules.v1.DryRunAnnotationR\x11\x64ryRunAnnotations\x12M\n\x0crule_outputs\x18\x03 \x03(\x0b\x32*.sift.rule_evaluation.v1.RulePreviewOutputR\x0bruleOutputs2\xd8\x06\n\x15RuleEvaluationService\x12\xc3\x02\n\rEvaluateRules\x12-.sift.rule_evaluation.v1.EvaluateRulesRequest\x1a..sift.rule_evaluation.v1.EvaluateRulesResponse\"\xd2\x01\x92\x41\xa7\x01\x12\rEvaluateRules\x1a\x95\x01\x45valuate rules from a designated source against a run or asset and return the total amount of annotations created and the ID of the generated report.\x82\xd3\xe4\x93\x02!\"\x1c/api/v1/rules/evaluate-rules:\x01*\x12\xda\x02\n\x14\x45valuateRulesPreview\x12\x34.sift.rule_evaluation.v1.EvaluateRulesPreviewRequest\x1a\x35.sift.rule_evaluation.v1.EvaluateRulesPreviewResponse\"\xd4\x01\x92\x41\xa1\x01\x12\x14\x45valuateRulesPreview\x1a\x88\x01Perform a dry run evaluation for existing rules or rule configurations against a run and return the annotations that would be generated.\x82\xd3\xe4\x93\x02)\"$/api/v1/rules/evaluate-rules:preview:\x01*\x1a\x9b\x01\x92\x41\x97\x01\x12\x1aService to evaluate rules.\x1ay\n\x1fRead more about what rules are.\x12Vhttps://customer.support.siftstack.com/servicedesk/customer/portal/2/article/265421102B\xca\x01\n\x1b\x63om.sift.rule_evaluation.v1B\x13RuleEvaluationProtoP\x01\xa2\x02\x03SRX\xaa\x02\x16Sift.RuleEvaluation.V1\xca\x02\x16Sift\\RuleEvaluation\\V1\xe2\x02\"Sift\\RuleEvaluation\\V1\\GPBMetadata\xea\x02\x18Sift::RuleEvaluation::V1\x92\x41\x1b\x12\x19\n\x17Rule Evaluation Serviceb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -75,29 +75,29 @@ _globals['_RULEEVALUATIONSERVICE'].methods_by_name['EvaluateRulesPreview']._loaded_options = None _globals['_RULEEVALUATIONSERVICE'].methods_by_name['EvaluateRulesPreview']._serialized_options = b'\222A\241\001\022\024EvaluateRulesPreview\032\210\001Perform a dry run evaluation for existing rules or rule configurations against a run and return the annotations that would be generated.\202\323\344\223\002)\"$/api/v1/rules/evaluate-rules:preview:\001*' _globals['_EVALUATERULESREQUEST']._serialized_start=293 - _globals['_EVALUATERULESREQUEST']._serialized_end=1031 - _globals['_RUNTIMERANGE']._serialized_start=1034 - _globals['_RUNTIMERANGE']._serialized_end=1269 - _globals['_ASSETSTIMERANGE']._serialized_start=1272 - _globals['_ASSETSTIMERANGE']._serialized_end=1479 - _globals['_EVALUATERULESFROMCURRENTRULEVERSIONS']._serialized_start=1481 - _globals['_EVALUATERULESFROMCURRENTRULEVERSIONS']._serialized_end=1588 - _globals['_EVALUATERULESFROMREPORTTEMPLATE']._serialized_start=1590 - _globals['_EVALUATERULESFROMREPORTTEMPLATE']._serialized_end=1710 - _globals['_EVALUATERULESFROMRULEVERSIONS']._serialized_start=1712 - _globals['_EVALUATERULESFROMRULEVERSIONS']._serialized_end=1790 - _globals['_EVALUATERULESANNOTATIONOPTIONS']._serialized_start=1792 - _globals['_EVALUATERULESANNOTATIONOPTIONS']._serialized_end=1886 - _globals['_EVALUATERULESRESPONSE']._serialized_start=1889 - _globals['_EVALUATERULESRESPONSE']._serialized_end=2072 - _globals['_EVALUATERULESPREVIEWREQUEST']._serialized_start=2075 - _globals['_EVALUATERULESPREVIEWREQUEST']._serialized_end=2681 - _globals['_EVALUATERULESFROMRULECONFIGS']._serialized_start=2683 - _globals['_EVALUATERULESFROMRULECONFIGS']._serialized_end=2778 - _globals['_RULEPREVIEWOUTPUT']._serialized_start=2781 - _globals['_RULEPREVIEWOUTPUT']._serialized_end=3013 - _globals['_EVALUATERULESPREVIEWRESPONSE']._serialized_start=3016 - _globals['_EVALUATERULESPREVIEWRESPONSE']._serialized_end=3269 - _globals['_RULEEVALUATIONSERVICE']._serialized_start=3272 - _globals['_RULEEVALUATIONSERVICE']._serialized_end=4128 + _globals['_EVALUATERULESREQUEST']._serialized_end=1083 + _globals['_RUNTIMERANGE']._serialized_start=1086 + _globals['_RUNTIMERANGE']._serialized_end=1321 + _globals['_ASSETSTIMERANGE']._serialized_start=1324 + _globals['_ASSETSTIMERANGE']._serialized_end=1531 + _globals['_EVALUATERULESFROMCURRENTRULEVERSIONS']._serialized_start=1533 + _globals['_EVALUATERULESFROMCURRENTRULEVERSIONS']._serialized_end=1640 + _globals['_EVALUATERULESFROMREPORTTEMPLATE']._serialized_start=1642 + _globals['_EVALUATERULESFROMREPORTTEMPLATE']._serialized_end=1762 + _globals['_EVALUATERULESFROMRULEVERSIONS']._serialized_start=1764 + _globals['_EVALUATERULESFROMRULEVERSIONS']._serialized_end=1842 + _globals['_EVALUATERULESANNOTATIONOPTIONS']._serialized_start=1844 + _globals['_EVALUATERULESANNOTATIONOPTIONS']._serialized_end=1938 + _globals['_EVALUATERULESRESPONSE']._serialized_start=1941 + _globals['_EVALUATERULESRESPONSE']._serialized_end=2124 + _globals['_EVALUATERULESPREVIEWREQUEST']._serialized_start=2127 + _globals['_EVALUATERULESPREVIEWREQUEST']._serialized_end=2733 + _globals['_EVALUATERULESFROMRULECONFIGS']._serialized_start=2735 + _globals['_EVALUATERULESFROMRULECONFIGS']._serialized_end=2830 + _globals['_RULEPREVIEWOUTPUT']._serialized_start=2833 + _globals['_RULEPREVIEWOUTPUT']._serialized_end=3065 + _globals['_EVALUATERULESPREVIEWRESPONSE']._serialized_start=3068 + _globals['_EVALUATERULESPREVIEWRESPONSE']._serialized_end=3321 + _globals['_RULEEVALUATIONSERVICE']._serialized_start=3324 + _globals['_RULEEVALUATIONSERVICE']._serialized_end=4180 # @@protoc_insertion_point(module_scope) diff --git a/python/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.pyi b/python/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.pyi index 1fbe917c5..c349c3b81 100644 --- a/python/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.pyi +++ b/python/lib/sift/rule_evaluation/v1/rule_evaluation_pb2.pyi @@ -25,9 +25,11 @@ class EvaluateRulesRequest(google.protobuf.message.Message): RULES_FIELD_NUMBER: builtins.int RULE_VERSIONS_FIELD_NUMBER: builtins.int REPORT_TEMPLATE_FIELD_NUMBER: builtins.int + ALL_APPLICABLE_RULES_FIELD_NUMBER: builtins.int ANNOTATION_OPTIONS_FIELD_NUMBER: builtins.int ORGANIZATION_ID_FIELD_NUMBER: builtins.int REPORT_NAME_FIELD_NUMBER: builtins.int + all_applicable_rules: builtins.bool organization_id: builtins.str """Only required if your user belongs to multiple organizations""" report_name: builtins.str @@ -55,16 +57,17 @@ class EvaluateRulesRequest(google.protobuf.message.Message): rules: global___EvaluateRulesFromCurrentRuleVersions | None = ..., rule_versions: global___EvaluateRulesFromRuleVersions | None = ..., report_template: global___EvaluateRulesFromReportTemplate | None = ..., + all_applicable_rules: builtins.bool = ..., annotation_options: global___EvaluateRulesAnnotationOptions | None = ..., organization_id: builtins.str = ..., report_name: builtins.str | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["_report_name", b"_report_name", "annotation_options", b"annotation_options", "assets", b"assets", "mode", b"mode", "report_name", b"report_name", "report_template", b"report_template", "rule_versions", b"rule_versions", "rules", b"rules", "run", b"run", "run_time_range", b"run_time_range", "time", b"time"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["_report_name", b"_report_name", "annotation_options", b"annotation_options", "assets", b"assets", "mode", b"mode", "organization_id", b"organization_id", "report_name", b"report_name", "report_template", b"report_template", "rule_versions", b"rule_versions", "rules", b"rules", "run", b"run", "run_time_range", b"run_time_range", "time", b"time"]) -> None: ... + def HasField(self, field_name: typing.Literal["_report_name", b"_report_name", "all_applicable_rules", b"all_applicable_rules", "annotation_options", b"annotation_options", "assets", b"assets", "mode", b"mode", "report_name", b"report_name", "report_template", b"report_template", "rule_versions", b"rule_versions", "rules", b"rules", "run", b"run", "run_time_range", b"run_time_range", "time", b"time"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_report_name", b"_report_name", "all_applicable_rules", b"all_applicable_rules", "annotation_options", b"annotation_options", "assets", b"assets", "mode", b"mode", "organization_id", b"organization_id", "report_name", b"report_name", "report_template", b"report_template", "rule_versions", b"rule_versions", "rules", b"rules", "run", b"run", "run_time_range", b"run_time_range", "time", b"time"]) -> None: ... @typing.overload def WhichOneof(self, oneof_group: typing.Literal["_report_name", b"_report_name"]) -> typing.Literal["report_name"] | None: ... @typing.overload - def WhichOneof(self, oneof_group: typing.Literal["mode", b"mode"]) -> typing.Literal["rules", "rule_versions", "report_template"] | None: ... + def WhichOneof(self, oneof_group: typing.Literal["mode", b"mode"]) -> typing.Literal["rules", "rule_versions", "report_template", "all_applicable_rules"] | None: ... @typing.overload def WhichOneof(self, oneof_group: typing.Literal["time", b"time"]) -> typing.Literal["run", "assets", "run_time_range"] | None: ... diff --git a/python/lib/sift/rules/v1/rules_pb2.py b/python/lib/sift/rules/v1/rules_pb2.py index 843f84461..9ddf730c5 100644 --- a/python/lib/sift/rules/v1/rules_pb2.py +++ b/python/lib/sift/rules/v1/rules_pb2.py @@ -19,9 +19,10 @@ from sift.annotations.v1 import annotations_pb2 as sift_dot_annotations_dot_v1_dot_annotations__pb2 from sift.common.type.v1 import resource_identifier_pb2 as sift_dot_common_dot_type_dot_v1_dot_resource__identifier__pb2 from sift.common.type.v1 import user_defined_functions_pb2 as sift_dot_common_dot_type_dot_v1_dot_user__defined__functions__pb2 +from sift.metadata.v1 import metadata_pb2 as sift_dot_metadata_dot_v1_dot_metadata__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19sift/rules/v1/rules.proto\x12\rsift.rules.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a%sift/annotations/v1/annotations.proto\x1a-sift/common/type/v1/resource_identifier.proto\x1a\x30sift/common/type/v1/user_defined_functions.proto\"\x99\x07\n\x04Rule\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12 \n\x08\x61sset_id\x18\x02 \x01(\tB\x05\x18\x01\xe0\x41\x02R\x07\x61ssetId\x12\x17\n\x04name\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x04name\x12%\n\x0b\x64\x65scription\x18\x04 \x01(\tB\x03\xe0\x41\x02R\x0b\x64\x65scription\x12\"\n\nis_enabled\x18\x06 \x01(\x08\x42\x03\xe0\x41\x02R\tisEnabled\x12\x42\n\x0c\x63reated_date\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0b\x63reatedDate\x12\x44\n\rmodified_date\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0cmodifiedDate\x12\x30\n\x12\x63reated_by_user_id\x18\t \x01(\tB\x03\xe0\x41\x02R\x0f\x63reatedByUserId\x12\x32\n\x13modified_by_user_id\x18\n \x01(\tB\x03\xe0\x41\x02R\x10modifiedByUserId\x12,\n\x0forganization_id\x18\x0b \x01(\tB\x03\xe0\x41\x02R\x0eorganizationId\x12\x41\n\nconditions\x18\x0c \x03(\x0b\x32\x1c.sift.rules.v1.RuleConditionB\x03\xe0\x41\x02R\nconditions\x12\x42\n\x0crule_version\x18\r \x01(\x0b\x32\x1a.sift.rules.v1.RuleVersionB\x03\xe0\x41\x02R\x0bruleVersion\x12\"\n\nclient_key\x18\x0e \x01(\tB\x03\xe0\x41\x01R\tclientKey\x12[\n\x13\x61sset_configuration\x18\x0f \x01(\x0b\x32%.sift.rules.v1.RuleAssetConfigurationB\x03\xe0\x41\x02R\x12\x61ssetConfiguration\x12W\n\x13\x63ontextual_channels\x18\x10 \x01(\x0b\x32!.sift.rules.v1.ContextualChannelsB\x03\xe0\x41\x02R\x12\x63ontextualChannels\x12\x42\n\x0c\x64\x65leted_date\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x01R\x0b\x64\x65letedDate\x12$\n\x0bis_external\x18\x12 \x01(\x08\x42\x03\xe0\x41\x02R\nisExternalJ\x04\x08\x05\x10\x06\"\x9b\x04\n\rRuleCondition\x12/\n\x11rule_condition_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x0fruleConditionId\x12\x1c\n\x07rule_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12K\n\nexpression\x18\x03 \x01(\x0b\x32&.sift.rules.v1.RuleConditionExpressionB\x03\xe0\x41\x02R\nexpression\x12\x42\n\x0c\x63reated_date\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0b\x63reatedDate\x12\x44\n\rmodified_date\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0cmodifiedDate\x12\x30\n\x12\x63reated_by_user_id\x18\x07 \x01(\tB\x03\xe0\x41\x02R\x0f\x63reatedByUserId\x12\x32\n\x13modified_by_user_id\x18\x08 \x01(\tB\x03\xe0\x41\x02R\x10modifiedByUserId\x12\x38\n\x07\x61\x63tions\x18\t \x03(\x0b\x32\x19.sift.rules.v1.RuleActionB\x03\xe0\x41\x02R\x07\x61\x63tions\x12>\n\x19rule_condition_version_id\x18\n \x01(\tB\x03\xe0\x41\x02R\x16ruleConditionVersionIdJ\x04\x08\x04\x10\x05\"\xa6\x04\n\nRuleAction\x12)\n\x0erule_action_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x0cruleActionId\x12/\n\x11rule_condition_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0fruleConditionId\x12?\n\x0b\x61\x63tion_type\x18\x03 \x01(\x0e\x32\x19.sift.rules.v1.ActionKindB\x03\xe0\x41\x02R\nactionType\x12Q\n\rconfiguration\x18\x04 \x01(\x0b\x32&.sift.rules.v1.RuleActionConfigurationB\x03\xe0\x41\x02R\rconfiguration\x12\x42\n\x0c\x63reated_date\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0b\x63reatedDate\x12\x44\n\rmodified_date\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0cmodifiedDate\x12\x30\n\x12\x63reated_by_user_id\x18\x07 \x01(\tB\x03\xe0\x41\x02R\x0f\x63reatedByUserId\x12\x32\n\x13modified_by_user_id\x18\x08 \x01(\tB\x03\xe0\x41\x02R\x10modifiedByUserId\x12\x38\n\x16rule_action_version_id\x18\t \x01(\tB\x03\xe0\x41\x02R\x13ruleActionVersionId\"N\n\x16RuleAssetConfiguration\x12\x1b\n\tasset_ids\x18\x01 \x03(\tR\x08\x61ssetIds\x12\x17\n\x07tag_ids\x18\x02 \x03(\tR\x06tagIds\"V\n\x12\x43ontextualChannels\x12@\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x1f.sift.rules.v1.ChannelReferenceB\x03\xe0\x41\x02R\x08\x63hannels\"\xb6\x01\n\x1f\x41ssetExpressionValidationResult\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\x12\"\n\nasset_name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tassetName\x12%\n\x0c\x61sset_tag_id\x18\x03 \x01(\tB\x03\xe0\x41\x01R\nassetTagId\x12\x1e\n\x05\x65rror\x18\x04 \x01(\tB\x03\xe0\x41\x01H\x00R\x05\x65rror\x88\x01\x01\x42\x08\n\x06_error\"\xc6\x03\n\x12SearchRulesRequest\x12\x19\n\x05limit\x18\x01 \x01(\rH\x00R\x05limit\x88\x01\x01\x12\x16\n\x06offset\x18\x02 \x01(\rR\x06offset\x12\x35\n\x05order\x18\x03 \x01(\x0e\x32\x1a.sift.rules.v1.SearchOrderH\x01R\x05order\x88\x01\x01\x12!\n\x0cname_matches\x18\x04 \x01(\tR\x0bnameMatches\x12%\n\x0e\x63\x61se_sensitive\x18\x05 \x01(\x08R\rcaseSensitive\x12\x16\n\x06regexp\x18\x06 \x01(\x08R\x06regexp\x12\x1e\n\x08order_by\x18\x07 \x01(\tH\x02R\x07orderBy\x88\x01\x01\x12\x19\n\x08rule_ids\x18\x08 \x03(\tR\x07ruleIds\x12\x1b\n\tasset_ids\x18\t \x03(\tR\x08\x61ssetIds\x12\'\n\x0finclude_deleted\x18\n \x01(\x08R\x0eincludeDeleted\x12\x42\n\nasset_tags\x18\x0b \x01(\x0b\x32#.sift.common.type.v1.NamedResourcesR\tassetTagsB\x08\n\x06_limitB\x08\n\x06_orderB\x0b\n\t_order_by\"`\n\x13SearchRulesResponse\x12\x19\n\x05\x63ount\x18\x01 \x01(\rB\x03\xe0\x41\x02R\x05\x63ount\x12.\n\x05rules\x18\x02 \x03(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x05rules\"R\n\x0eGetRuleRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x01R\x06ruleId\x12\"\n\nclient_key\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tclientKey\"?\n\x0fGetRuleResponse\x12,\n\x04rule\x18\x01 \x01(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x04rule\"\\\n\x14\x42\x61tchGetRulesRequest\x12\x1e\n\x08rule_ids\x18\x01 \x03(\tB\x03\xe0\x41\x01R\x07ruleIds\x12$\n\x0b\x63lient_keys\x18\x02 \x03(\tB\x03\xe0\x41\x01R\nclientKeys\"G\n\x15\x42\x61tchGetRulesResponse\x12.\n\x05rules\x18\x01 \x03(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x05rules\"R\n\x11\x43reateRuleRequest\x12=\n\x06update\x18\x01 \x01(\x0b\x32 .sift.rules.v1.UpdateRuleRequestB\x03\xe0\x41\x02R\x06update\"2\n\x12\x43reateRuleResponse\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\"\xdd\x04\n\x11UpdateRuleRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tH\x00R\x06ruleId\x88\x01\x01\x12\x17\n\x04name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x04name\x12%\n\x0b\x64\x65scription\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x0b\x64\x65scription\x12 \n\x08\x61sset_id\x18\x04 \x01(\tB\x05\x18\x01\xe0\x41\x01R\x07\x61ssetId\x12\"\n\nis_enabled\x18\x05 \x01(\x08\x42\x03\xe0\x41\x02R\tisEnabled\x12J\n\nconditions\x18\x06 \x03(\x0b\x32%.sift.rules.v1.UpdateConditionRequestB\x03\xe0\x41\x02R\nconditions\x12\'\n\x0forganization_id\x18\x07 \x01(\tR\x0eorganizationId\x12#\n\rversion_notes\x18\x08 \x01(\tR\x0cversionNotes\x12\"\n\nclient_key\x18\t \x01(\tH\x01R\tclientKey\x88\x01\x01\x12V\n\x13\x61sset_configuration\x18\n \x01(\x0b\x32%.sift.rules.v1.RuleAssetConfigurationR\x12\x61ssetConfiguration\x12R\n\x13\x63ontextual_channels\x18\x0b \x01(\x0b\x32!.sift.rules.v1.ContextualChannelsR\x12\x63ontextualChannels\x12\x1f\n\x0bis_external\x18\x0c \x01(\x08R\nisExternalB\n\n\x08_rule_idB\r\n\x0b_client_key\"\xf5\x01\n\x16UpdateConditionRequest\x12/\n\x11rule_condition_id\x18\x01 \x01(\tH\x00R\x0fruleConditionId\x88\x01\x01\x12K\n\nexpression\x18\x03 \x01(\x0b\x32&.sift.rules.v1.RuleConditionExpressionB\x03\xe0\x41\x02R\nexpression\x12\x41\n\x07\x61\x63tions\x18\x04 \x03(\x0b\x32\".sift.rules.v1.UpdateActionRequestB\x03\xe0\x41\x02R\x07\x61\x63tionsB\x14\n\x12_rule_condition_idJ\x04\x08\x02\x10\x03\"\xe7\x01\n\x13UpdateActionRequest\x12)\n\x0erule_action_id\x18\x01 \x01(\tH\x00R\x0cruleActionId\x88\x01\x01\x12?\n\x0b\x61\x63tion_type\x18\x02 \x01(\x0e\x32\x19.sift.rules.v1.ActionKindB\x03\xe0\x41\x02R\nactionType\x12Q\n\rconfiguration\x18\x03 \x01(\x0b\x32&.sift.rules.v1.RuleActionConfigurationB\x03\xe0\x41\x02R\rconfigurationB\x11\n\x0f_rule_action_id\"2\n\x12UpdateRuleResponse\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\"\x83\x02\n\x10ValidationResult\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x01R\x06ruleId\x12\"\n\nclient_key\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tclientKey\x12\x82\x01\n#asset_expression_validation_results\x18\x03 \x03(\x0b\x32..sift.rules.v1.AssetExpressionValidationResultB\x03\xe0\x41\x02R assetExpressionValidationResults\x12\x1e\n\x05\x65rror\x18\x04 \x01(\tB\x03\xe0\x41\x01H\x00R\x05\x65rror\x88\x01\x01\x42\x08\n\x06_error\"\xcb\x01\n\x17\x42\x61tchUpdateRulesRequest\x12;\n\x05rules\x18\x01 \x03(\x0b\x32 .sift.rules.v1.UpdateRuleRequestB\x03\xe0\x41\x02R\x05rules\x12(\n\rvalidate_only\x18\x02 \x01(\x08\x42\x03\xe0\x41\x01R\x0cvalidateOnly\x12I\n\x1eoverride_expression_validation\x18\x03 \x01(\x08\x42\x03\xe0\x41\x02R\x1coverrideExpressionValidation\"\x9d\x04\n\x18\x42\x61tchUpdateRulesResponse\x12\x1d\n\x07success\x18\x01 \x01(\x08\x42\x03\xe0\x41\x02R\x07success\x12\x33\n\x13rules_created_count\x18\x02 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesCreatedCount\x12\x33\n\x13rules_updated_count\x18\x03 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesUpdatedCount\x12(\n\rvalidate_only\x18\x04 \x01(\x08\x42\x03\xe0\x41\x02R\x0cvalidateOnly\x12S\n\x12validation_results\x18\x05 \x03(\x0b\x32\x1f.sift.rules.v1.ValidationResultB\x03\xe0\x41\x02R\x11validationResults\x12v\n\x18\x63reated_rule_identifiers\x18\x06 \x03(\x0b\x32\x37.sift.rules.v1.BatchUpdateRulesResponse.RuleIdentifiersB\x03\xe0\x41\x02R\x16\x63reatedRuleIdentifiers\x1a\x80\x01\n\x0fRuleIdentifiers\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12\x17\n\x04name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x04name\x12\'\n\nclient_key\x18\x03 \x01(\tB\x03\xe0\x41\x01H\x00R\tclientKey\x88\x01\x01\x42\r\n\x0b_client_key\"U\n\x11\x44\x65leteRuleRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x01R\x06ruleId\x12\"\n\nclient_key\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tclientKey\"\x14\n\x12\x44\x65leteRuleResponse\"_\n\x17\x42\x61tchDeleteRulesRequest\x12\x1e\n\x08rule_ids\x18\x01 \x03(\tB\x03\xe0\x41\x01R\x07ruleIds\x12$\n\x0b\x63lient_keys\x18\x02 \x03(\tB\x03\xe0\x41\x01R\nclientKeys\"\x1a\n\x18\x42\x61tchDeleteRulesResponse\"W\n\x13UndeleteRuleRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x01R\x06ruleId\x12\"\n\nclient_key\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tclientKey\"\x16\n\x14UndeleteRuleResponse\"a\n\x19\x42\x61tchUndeleteRulesRequest\x12\x1e\n\x08rule_ids\x18\x01 \x03(\tB\x03\xe0\x41\x01R\x07ruleIds\x12$\n\x0b\x63lient_keys\x18\x02 \x03(\tB\x03\xe0\x41\x01R\nclientKeys\"\x1c\n\x1a\x42\x61tchUndeleteRulesResponse\"C\n\x1dViewHumanFriendlyRulesRequest\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId:\x02\x18\x01\"H\n\x1eViewHumanFriendlyRulesResponse\x12\"\n\nrules_json\x18\x01 \x01(\tB\x03\xe0\x41\x02R\trulesJson:\x02\x18\x01\"\x97\x01\n\x1fUpdateHumanFriendlyRulesRequest\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\x12\"\n\nrules_json\x18\x02 \x01(\tB\x03\xe0\x41\x02R\trulesJson\x12,\n\x0forganization_id\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x0eorganizationId:\x02\x18\x01\"\x8c\x01\n UpdateHumanFriendlyRulesResponse\x12\x1d\n\x07success\x18\x01 \x01(\x08\x42\x03\xe0\x41\x02R\x07success\x12$\n\x0brules_count\x18\x02 \x01(\x05\x42\x03\xe0\x41\x02R\nrulesCount\x12\x1f\n\x08messages\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x08messages:\x02\x18\x01\"6\n\x14ViewJsonRulesRequest\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\";\n\x15ViewJsonRulesResponse\x12\"\n\nrules_json\x18\x01 \x01(\tB\x03\xe0\x41\x02R\trulesJson\"\x84\x01\n\x10JsonRulesRequest\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\x12\"\n\nrules_json\x18\x02 \x01(\tB\x03\xe0\x41\x02R\trulesJson\x12,\n\x0forganization_id\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x0eorganizationId\"\xc1\x02\n\x11JsonRulesResponse\x12\x1d\n\x07success\x18\x01 \x01(\x08\x42\x03\xe0\x41\x02R\x07success\x12/\n\x11total_rules_count\x18\x02 \x01(\x05\x42\x03\xe0\x41\x02R\x0ftotalRulesCount\x12\x33\n\x13rules_created_count\x18\x03 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesCreatedCount\x12\x33\n\x13rules_updated_count\x18\x04 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesUpdatedCount\x12\x33\n\x13rules_deleted_count\x18\x05 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesDeletedCount\x12*\n\x0e\x65rror_messages\x18\x06 \x01(\tH\x00R\rerrorMessages\x88\x01\x01\x42\x11\n\x0f_error_messages\"Z\n\x18ValidateJsonRulesRequest\x12>\n\x07request\x18\x01 \x01(\x0b\x32\x1f.sift.rules.v1.JsonRulesRequestB\x03\xe0\x41\x02R\x07request\"^\n\x19ValidateJsonRulesResponse\x12\x41\n\x08response\x18\x01 \x01(\x0b\x32 .sift.rules.v1.JsonRulesResponseB\x03\xe0\x41\x02R\x08response\"X\n\x16UpdateJsonRulesRequest\x12>\n\x07request\x18\x01 \x01(\x0b\x32\x1f.sift.rules.v1.JsonRulesRequestB\x03\xe0\x41\x02R\x07request\"\\\n\x17UpdateJsonRulesResponse\x12\x41\n\x08response\x18\x01 \x01(\x0b\x32 .sift.rules.v1.JsonRulesResponseB\x03\xe0\x41\x02R\x08response\"\x95\x01\n\x10ListRulesRequest\x12 \n\tpage_size\x18\x01 \x01(\rB\x03\xe0\x41\x01R\x08pageSize\x12\"\n\npage_token\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tpageToken\x12\x1b\n\x06\x66ilter\x18\x03 \x01(\tB\x03\xe0\x41\x01R\x06\x66ilter\x12\x1e\n\x08order_by\x18\x04 \x01(\tB\x03\xe0\x41\x01R\x07orderBy\"k\n\x11ListRulesResponse\x12.\n\x05rules\x18\x01 \x03(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x05rules\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\x95\x01\n\x17ListRuleVersionsRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12 \n\tpage_size\x18\x02 \x01(\rB\x03\xe0\x41\x01R\x08pageSize\x12\"\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01R\tpageToken\x12\x16\n\x06\x66ilter\x18\x04 \x01(\tR\x06\x66ilter\"\x9a\x03\n\x0bRuleVersion\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12+\n\x0frule_version_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\rruleVersionId\x12\x1d\n\x07version\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x07version\x12\x42\n\x0c\x63reated_date\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0b\x63reatedDate\x12\x30\n\x12\x63reated_by_user_id\x18\x05 \x01(\tB\x03\xe0\x41\x02R\x0f\x63reatedByUserId\x12(\n\rversion_notes\x18\x06 \x01(\tB\x03\xe0\x41\x02R\x0cversionNotes\x12=\n\x18generated_change_message\x18\x07 \x01(\tB\x03\xe0\x41\x02R\x16generatedChangeMessage\x12\x42\n\x0c\x64\x65leted_date\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x01R\x0b\x64\x65letedDate\"\x88\x01\n\x18ListRuleVersionsResponse\x12\x44\n\rrule_versions\x18\x01 \x03(\x0b\x32\x1a.sift.rules.v1.RuleVersionB\x03\xe0\x41\x02R\x0cruleVersions\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"D\n\x15GetRuleVersionRequest\x12+\n\x0frule_version_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\rruleVersionId\"F\n\x16GetRuleVersionResponse\x12,\n\x04rule\x18\x01 \x01(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x04rule\"L\n\x1b\x42\x61tchGetRuleVersionsRequest\x12-\n\x10rule_version_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x0eruleVersionIds\"N\n\x1c\x42\x61tchGetRuleVersionsResponse\x12.\n\x05rules\x18\x01 \x03(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x05rules\"\xb2\x02\n\x17RuleConditionExpression\x12r\n\x19single_channel_comparison\x18\x01 \x01(\x0b\x32\x30.sift.rules.v1.SingleChannelComparisonExpressionB\x02\x18\x01H\x00R\x17singleChannelComparison\x12W\n\x12\x63\x61lculated_channel\x18\x02 \x01(\x0b\x32&.sift.rules.v1.CalculatedChannelConfigH\x00R\x11\x63\x61lculatedChannel\x12<\n\x0bpython_code\x18\x03 \x01(\x0b\x32\x19.sift.rules.v1.PythonCodeH\x00R\npythonCodeB\x0c\n\nexpression\"\xcb\x02\n!SingleChannelComparisonExpression\x12\x30\n\x11\x63hannel_component\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x10\x63hannelComponent\x12&\n\x0c\x63hannel_name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0b\x63hannelName\x12G\n\ncomparator\x18\x03 \x01(\x0e\x32\".sift.rules.v1.ConditionComparatorB\x03\xe0\x41\x02R\ncomparator\x12\x18\n\x06\x64ouble\x18\x04 \x01(\x01H\x00R\x06\x64ouble\x12\x18\n\x06string\x18\x05 \x01(\tH\x00R\x06string\x12\x42\n\nlast_value\x18\x06 \x01(\x0b\x32!.sift.rules.v1.LastValueThresholdH\x00R\tlastValueB\x0b\n\tthreshold\"\x14\n\x12LastValueThreshold\"\xfb\x02\n\x17\x43\x61lculatedChannelConfig\x12q\n\x12\x63hannel_references\x18\x01 \x03(\x0b\x32=.sift.rules.v1.CalculatedChannelConfig.ChannelReferencesEntryB\x03\xe0\x41\x02R\x11\x63hannelReferences\x12#\n\nexpression\x18\x02 \x01(\tB\x03\xe0\x41\x02R\nexpression\x12\x61\n\x15\x66unction_dependencies\x18\x03 \x03(\x0b\x32\'.sift.common.type.v1.FunctionDependencyB\x03\xe0\x41\x01R\x14\x66unctionDependencies\x1a\x65\n\x16\x43hannelReferencesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32\x1f.sift.rules.v1.ChannelReferenceR\x05value:\x02\x38\x01\"N\n\x10\x43hannelReference\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x04name\x12!\n\tcomponent\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tcomponent\"T\n\x16PythonChannelReference\x12!\n\treference\x18\x01 \x01(\tB\x03\xe0\x41\x02R\treference\x12\x17\n\x04name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x04name\"\xa9\x01\n\nPythonCode\x12Y\n\x12\x63hannel_references\x18\x01 \x03(\x0b\x32%.sift.rules.v1.PythonChannelReferenceB\x03\xe0\x41\x02R\x11\x63hannelReferences\x12\x17\n\x04\x63ode\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x04\x63ode\x12\'\n\x0c\x64\x65pendencies\x18\x03 \x01(\tB\x03\xe0\x41\x01R\x0c\x64\x65pendencies\"\xd0\x01\n\x17RuleActionConfiguration\x12T\n\x0cnotification\x18\x01 \x01(\x0b\x32..sift.rules.v1.NotificationActionConfigurationH\x00R\x0cnotification\x12N\n\nannotation\x18\x02 \x01(\x0b\x32,.sift.rules.v1.AnnotationActionConfigurationH\x00R\nannotationB\x0f\n\rconfiguration\"T\n\x1fNotificationActionConfiguration\x12\x31\n\x12recipient_user_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x10recipientUserIds\"\xd7\x01\n\x1d\x41nnotationActionConfiguration\x12\x1c\n\x07tag_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x06tagIds\x12L\n\x0f\x61nnotation_type\x18\x02 \x01(\x0e\x32#.sift.annotations.v1.AnnotationTypeR\x0e\x61nnotationType\x12\x32\n\x13\x61ssigned_to_user_id\x18\x03 \x01(\tH\x00R\x10\x61ssignedToUserId\x88\x01\x01\x42\x16\n\x14_assigned_to_user_id\"\x8e\x02\n\x14\x45valuateRulesRequest\x12\x1e\n\x08rule_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x07ruleIds\x12X\n\x12\x61nnotation_options\x18\x02 \x01(\x0b\x32).sift.rules.v1.EvaluatedAnnotationOptionsR\x11\x61nnotationOptions\x12\x17\n\x06run_id\x18\x03 \x01(\tH\x00R\x05runId\x12>\n\ntime_range\x18\x04 \x01(\x0b\x32\x1d.sift.rules.v1.TimeRangeQueryH\x00R\ttimeRange\x12\x17\n\x07\x64ry_run\x18\x05 \x01(\x08R\x06\x64ryRun:\x02\x18\x01\x42\x06\n\x04time\"5\n\x1a\x45valuatedAnnotationOptions\x12\x17\n\x07tag_ids\x18\x01 \x03(\tR\x06tagIds\"\x82\x01\n\x0eTimeRangeQuery\x12\x39\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartTime\x12\x35\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x07\x65ndTime\"\xfd\x01\n\x15\x45valuateRulesResponse\x12\x38\n\x18\x63reated_annotation_count\x18\x01 \x01(\x05R\x16\x63reatedAnnotationCount\x12O\n\x13\x64ry_run_annotations\x18\x02 \x03(\x0b\x32\x1f.sift.rules.v1.DryRunAnnotationR\x11\x64ryRunAnnotations\x12\x1a\n\x06job_id\x18\x03 \x01(\tH\x00R\x05jobId\x88\x01\x01\x12 \n\treport_id\x18\x04 \x01(\tH\x01R\x08reportId\x88\x01\x01:\x02\x18\x01\x42\t\n\x07_job_idB\x0c\n\n_report_id\"\xf7\x01\n\x10\x44ryRunAnnotation\x12!\n\x0c\x63ondition_id\x18\x01 \x01(\tR\x0b\x63onditionId\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12>\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\tstartTime\x12:\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x07\x65ndTime\x12\x30\n\x14\x63ondition_version_id\x18\x05 \x01(\tR\x12\x63onditionVersionId*\\\n\x0bSearchOrder\x12 \n\x18SEARCH_ORDER_UNSPECIFIED\x10\x00\x1a\x02\x08\x01\x12\x14\n\x10SEARCH_ORDER_ASC\x10\x01\x12\x15\n\x11SEARCH_ORDER_DESC\x10\x02*\\\n\nActionKind\x12\x1f\n\x17\x41\x43TION_KIND_UNSPECIFIED\x10\x00\x1a\x02\x08\x01\x12\x10\n\x0cNOTIFICATION\x10\x01\x12\x0e\n\nANNOTATION\x10\x02\x12\x0b\n\x07WEBHOOK\x10\x03*\xad\x01\n\x13\x43onditionComparator\x12(\n CONDITION_COMPARATOR_UNSPECIFIED\x10\x00\x1a\x02\x08\x01\x12\r\n\tLESS_THAN\x10\x01\x12\x16\n\x12LESS_THAN_OR_EQUAL\x10\x02\x12\x10\n\x0cGREATER_THAN\x10\x03\x12\x19\n\x15GREATER_THAN_OR_EQUAL\x10\x04\x12\t\n\x05\x45QUAL\x10\x05\x12\r\n\tNOT_EQUAL\x10\x06\x32\xd0 \n\x0bRuleService\x12\xb9\x01\n\x0bSearchRules\x12!.sift.rules.v1.SearchRulesRequest\x1a\".sift.rules.v1.SearchRulesResponse\"c\x92\x41\x41\x12\x0bSearchRules\x1a\x32Queries rules based on provided search parameters.\x82\xd3\xe4\x93\x02\x19\"\x14/api/v1/rules/search:\x01*\x12\x94\x01\n\x07GetRule\x12\x1d.sift.rules.v1.GetRuleRequest\x1a\x1e.sift.rules.v1.GetRuleResponse\"J\x92\x41\x32\x12\x07GetRule\x1a\'Retrieves the latest version of a rule.\x82\xd3\xe4\x93\x02\x0f\x12\r/api/v1/rules\x12\xaa\x01\n\rBatchGetRules\x12#.sift.rules.v1.BatchGetRulesRequest\x1a$.sift.rules.v1.BatchGetRulesResponse\"N\x92\x41*\x12\rBatchGetRules\x1a\x19Retrieves multiple rules.\x82\xd3\xe4\x93\x02\x1b\"\x16/api/v1/rules:batchGet:\x01*\x12\x8b\x01\n\nCreateRule\x12 .sift.rules.v1.CreateRuleRequest\x1a!.sift.rules.v1.CreateRuleResponse\"8\x92\x41\x1d\x12\nCreateRule\x1a\x0f\x43reates a rule.\x82\xd3\xe4\x93\x02\x12\"\r/api/v1/rules:\x01*\x12\x95\x01\n\nUpdateRule\x12 .sift.rules.v1.UpdateRuleRequest\x1a!.sift.rules.v1.UpdateRuleResponse\"B\x92\x41\'\x12\nUpdateRule\x1a\x19Updates an existing rule.\x82\xd3\xe4\x93\x02\x12\x1a\r/api/v1/rules:\x01*\x12\xda\x01\n\x10\x42\x61tchUpdateRules\x12&.sift.rules.v1.BatchUpdateRulesRequest\x1a\'.sift.rules.v1.BatchUpdateRulesResponse\"u\x92\x41N\x12\x10\x42\x61tchUpdateRules\x1a:Updates existing rules or creates rules that do not exist.\x82\xd3\xe4\x93\x02\x1e\x1a\x19/api/v1/rules:batchUpdate:\x01*\x12\x92\x01\n\nDeleteRule\x12 .sift.rules.v1.DeleteRuleRequest\x1a!.sift.rules.v1.DeleteRuleResponse\"?\x92\x41\x1d\x12\nDeleteRule\x1a\x0f\x44\x65letes a rule.\x82\xd3\xe4\x93\x02\x19\"\x14/api/v1/rules/delete:\x01*\x12\xb7\x01\n\x10\x42\x61tchDeleteRules\x12&.sift.rules.v1.BatchDeleteRulesRequest\x1a\'.sift.rules.v1.BatchDeleteRulesResponse\"R\x92\x41+\x12\x10\x42\x61tchDeleteRules\x1a\x17\x44\x65letes multiple rules.\x82\xd3\xe4\x93\x02\x1e\"\x19/api/v1/rules/batchDelete:\x01*\x12\x9e\x01\n\x0cUndeleteRule\x12\".sift.rules.v1.UndeleteRuleRequest\x1a#.sift.rules.v1.UndeleteRuleResponse\"E\x92\x41!\x12\x0cUndeleteRule\x1a\x11Undeletes a rule.\x82\xd3\xe4\x93\x02\x1b\"\x16/api/v1/rules/undelete:\x01*\x12\xc3\x01\n\x12\x42\x61tchUndeleteRules\x12(.sift.rules.v1.BatchUndeleteRulesRequest\x1a).sift.rules.v1.BatchUndeleteRulesResponse\"X\x92\x41/\x12\x12\x42\x61tchUndeleteRules\x1a\x19Undeletes multiple rules.\x82\xd3\xe4\x93\x02 \"\x1b/api/v1/rules/batchUndelete:\x01*\x12\xdf\x01\n\rEvaluateRules\x12#.sift.rules.v1.EvaluateRulesRequest\x1a$.sift.rules.v1.EvaluateRulesResponse\"\x82\x01\x88\x02\x01\x92\x41[\x12\rEvaluateRules\x1aJEvaluates the provided rules and generate annotations based on the result.\x82\xd3\xe4\x93\x02\x1b\"\x16/api/v1/rules/evaluate:\x01*\x12\x84\x02\n\x16ViewHumanFriendlyRules\x12,.sift.rules.v1.ViewHumanFriendlyRulesRequest\x1a-.sift.rules.v1.ViewHumanFriendlyRulesResponse\"\x8c\x01\x88\x02\x01\x92\x41_\x12\x16ViewHumanFriendlyRules\x1a\x45Retrieve a JSON object containing all of the rules for a given asset.\x82\xd3\xe4\x93\x02!\x12\x1f/api/v1/rules:viewHumanFriendly\x12\xd6\x01\n\rViewJsonRules\x12#.sift.rules.v1.ViewJsonRulesRequest\x1a$.sift.rules.v1.ViewJsonRulesResponse\"z\x88\x02\x01\x92\x41V\x12\rViewJsonRules\x1a\x45Retrieve a JSON object containing all of the rules for a given asset.\x82\xd3\xe4\x93\x02\x18\x12\x16/api/v1/rules:viewJson\x12\x94\x02\n\x18UpdateHumanFriendlyRules\x12..sift.rules.v1.UpdateHumanFriendlyRulesRequest\x1a/.sift.rules.v1.UpdateHumanFriendlyRulesResponse\"\x96\x01\x88\x02\x01\x92\x41\x64\x12\x18UpdateHumanFriendlyRules\x1aHBatch update rules given the `rules_json` which is a JSON list of rules.\x82\xd3\xe4\x93\x02&\"!/api/v1/rules:updateHumanFriendly:\x01*\x12\x80\x02\n\x11ValidateJsonRules\x12\'.sift.rules.v1.ValidateJsonRulesRequest\x1a(.sift.rules.v1.ValidateJsonRulesResponse\"\x97\x01\x88\x02\x01\x92\x41l\x12\x11ValidateJsonRules\x1aWValidate a batch update for rules given the `rules_json` which is a JSON list of rules.\x82\xd3\xe4\x93\x02\x1f\"\x1a/api/v1/rules:validateJson:\x01*\x12\xe7\x01\n\x0fUpdateJsonRules\x12%.sift.rules.v1.UpdateJsonRulesRequest\x1a&.sift.rules.v1.UpdateJsonRulesResponse\"\x84\x01\x88\x02\x01\x92\x41[\x12\x0fUpdateJsonRules\x1aHBatch update rules given the `rules_json` which is a JSON list of rules.\x82\xd3\xe4\x93\x02\x1d\"\x18/api/v1/rules:updateJson:\x01*\x12\x94\x01\n\tListRules\x12\x1f.sift.rules.v1.ListRulesRequest\x1a .sift.rules.v1.ListRulesResponse\"D\x92\x41\'\x12\tListRules\x1a\x1aRetrieves a list of rules.\x82\xd3\xe4\x93\x02\x14\x12\x12/api/v1/rules:list\x12\xd9\x01\n\x10ListRuleVersions\x12&.sift.rules.v1.ListRuleVersionsRequest\x1a\'.sift.rules.v1.ListRuleVersionsResponse\"t\x92\x41I\x12\x10ListRuleVersions\x1a\x35Retrieves a list of rule versions for the given rule.\x82\xd3\xe4\x93\x02\"\x12 /api/v1/rules/{rule_id}/versions\x12\xb8\x01\n\x0eGetRuleVersion\x12$.sift.rules.v1.GetRuleVersionRequest\x1a%.sift.rules.v1.GetRuleVersionResponse\"Y\x92\x41\x39\x12\x0eGetRuleVersion\x1a\'Retrieves a specific version of a rule.\x82\xd3\xe4\x93\x02\x17\x12\x15/api/v1/rules:version\x12\xdf\x01\n\x14\x42\x61tchGetRuleVersions\x12*.sift.rules.v1.BatchGetRuleVersionsRequest\x1a+.sift.rules.v1.BatchGetRuleVersionsResponse\"n\x92\x41\x42\x12\x14\x42\x61tchGetRuleVersions\x1a*Retrieves multiple rules by rule versions.\x82\xd3\xe4\x93\x02#\"\x1e/api/v1/rules:batchGetVersions:\x01*\x1a\xb1\x01\x92\x41\xad\x01\x12\x30Service to programmatically interact with rules.\x1ay\n\x1fRead more about what rules are.\x12Vhttps://customer.support.siftstack.com/servicedesk/customer/portal/2/article/265421102B\x88\x01\n\x11\x63om.sift.rules.v1B\nRulesProtoP\x01\xa2\x02\x03SRX\xaa\x02\rSift.Rules.V1\xca\x02\rSift\\Rules\\V1\xe2\x02\x19Sift\\Rules\\V1\\GPBMetadata\xea\x02\x0fSift::Rules::V1\x92\x41\x10\x12\x0e\n\x0cRule Serviceb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19sift/rules/v1/rules.proto\x12\rsift.rules.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a%sift/annotations/v1/annotations.proto\x1a-sift/common/type/v1/resource_identifier.proto\x1a\x30sift/common/type/v1/user_defined_functions.proto\x1a\x1fsift/metadata/v1/metadata.proto\"\xdb\x07\n\x04Rule\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12 \n\x08\x61sset_id\x18\x02 \x01(\tB\x05\x18\x01\xe0\x41\x02R\x07\x61ssetId\x12\x17\n\x04name\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x04name\x12%\n\x0b\x64\x65scription\x18\x04 \x01(\tB\x03\xe0\x41\x02R\x0b\x64\x65scription\x12\"\n\nis_enabled\x18\x06 \x01(\x08\x42\x03\xe0\x41\x02R\tisEnabled\x12\x42\n\x0c\x63reated_date\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0b\x63reatedDate\x12\x44\n\rmodified_date\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0cmodifiedDate\x12\x30\n\x12\x63reated_by_user_id\x18\t \x01(\tB\x03\xe0\x41\x02R\x0f\x63reatedByUserId\x12\x32\n\x13modified_by_user_id\x18\n \x01(\tB\x03\xe0\x41\x02R\x10modifiedByUserId\x12,\n\x0forganization_id\x18\x0b \x01(\tB\x03\xe0\x41\x02R\x0eorganizationId\x12\x41\n\nconditions\x18\x0c \x03(\x0b\x32\x1c.sift.rules.v1.RuleConditionB\x03\xe0\x41\x02R\nconditions\x12\x42\n\x0crule_version\x18\r \x01(\x0b\x32\x1a.sift.rules.v1.RuleVersionB\x03\xe0\x41\x02R\x0bruleVersion\x12\"\n\nclient_key\x18\x0e \x01(\tB\x03\xe0\x41\x01R\tclientKey\x12[\n\x13\x61sset_configuration\x18\x0f \x01(\x0b\x32%.sift.rules.v1.RuleAssetConfigurationB\x03\xe0\x41\x02R\x12\x61ssetConfiguration\x12W\n\x13\x63ontextual_channels\x18\x10 \x01(\x0b\x32!.sift.rules.v1.ContextualChannelsB\x03\xe0\x41\x02R\x12\x63ontextualChannels\x12\x42\n\x0c\x64\x65leted_date\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x01R\x0b\x64\x65letedDate\x12$\n\x0bis_external\x18\x12 \x01(\x08\x42\x03\xe0\x41\x02R\nisExternal\x12@\n\x08metadata\x18\x13 \x03(\x0b\x32\x1f.sift.metadata.v1.MetadataValueB\x03\xe0\x41\x02R\x08metadataJ\x04\x08\x05\x10\x06\"\x9b\x04\n\rRuleCondition\x12/\n\x11rule_condition_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x0fruleConditionId\x12\x1c\n\x07rule_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12K\n\nexpression\x18\x03 \x01(\x0b\x32&.sift.rules.v1.RuleConditionExpressionB\x03\xe0\x41\x02R\nexpression\x12\x42\n\x0c\x63reated_date\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0b\x63reatedDate\x12\x44\n\rmodified_date\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0cmodifiedDate\x12\x30\n\x12\x63reated_by_user_id\x18\x07 \x01(\tB\x03\xe0\x41\x02R\x0f\x63reatedByUserId\x12\x32\n\x13modified_by_user_id\x18\x08 \x01(\tB\x03\xe0\x41\x02R\x10modifiedByUserId\x12\x38\n\x07\x61\x63tions\x18\t \x03(\x0b\x32\x19.sift.rules.v1.RuleActionB\x03\xe0\x41\x02R\x07\x61\x63tions\x12>\n\x19rule_condition_version_id\x18\n \x01(\tB\x03\xe0\x41\x02R\x16ruleConditionVersionIdJ\x04\x08\x04\x10\x05\"\xa6\x04\n\nRuleAction\x12)\n\x0erule_action_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x0cruleActionId\x12/\n\x11rule_condition_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0fruleConditionId\x12?\n\x0b\x61\x63tion_type\x18\x03 \x01(\x0e\x32\x19.sift.rules.v1.ActionKindB\x03\xe0\x41\x02R\nactionType\x12Q\n\rconfiguration\x18\x04 \x01(\x0b\x32&.sift.rules.v1.RuleActionConfigurationB\x03\xe0\x41\x02R\rconfiguration\x12\x42\n\x0c\x63reated_date\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0b\x63reatedDate\x12\x44\n\rmodified_date\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0cmodifiedDate\x12\x30\n\x12\x63reated_by_user_id\x18\x07 \x01(\tB\x03\xe0\x41\x02R\x0f\x63reatedByUserId\x12\x32\n\x13modified_by_user_id\x18\x08 \x01(\tB\x03\xe0\x41\x02R\x10modifiedByUserId\x12\x38\n\x16rule_action_version_id\x18\t \x01(\tB\x03\xe0\x41\x02R\x13ruleActionVersionId\"N\n\x16RuleAssetConfiguration\x12\x1b\n\tasset_ids\x18\x01 \x03(\tR\x08\x61ssetIds\x12\x17\n\x07tag_ids\x18\x02 \x03(\tR\x06tagIds\"V\n\x12\x43ontextualChannels\x12@\n\x08\x63hannels\x18\x01 \x03(\x0b\x32\x1f.sift.rules.v1.ChannelReferenceB\x03\xe0\x41\x02R\x08\x63hannels\"\xb6\x01\n\x1f\x41ssetExpressionValidationResult\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\x12\"\n\nasset_name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tassetName\x12%\n\x0c\x61sset_tag_id\x18\x03 \x01(\tB\x03\xe0\x41\x01R\nassetTagId\x12\x1e\n\x05\x65rror\x18\x04 \x01(\tB\x03\xe0\x41\x01H\x00R\x05\x65rror\x88\x01\x01\x42\x08\n\x06_error\"\xc6\x03\n\x12SearchRulesRequest\x12\x19\n\x05limit\x18\x01 \x01(\rH\x00R\x05limit\x88\x01\x01\x12\x16\n\x06offset\x18\x02 \x01(\rR\x06offset\x12\x35\n\x05order\x18\x03 \x01(\x0e\x32\x1a.sift.rules.v1.SearchOrderH\x01R\x05order\x88\x01\x01\x12!\n\x0cname_matches\x18\x04 \x01(\tR\x0bnameMatches\x12%\n\x0e\x63\x61se_sensitive\x18\x05 \x01(\x08R\rcaseSensitive\x12\x16\n\x06regexp\x18\x06 \x01(\x08R\x06regexp\x12\x1e\n\x08order_by\x18\x07 \x01(\tH\x02R\x07orderBy\x88\x01\x01\x12\x19\n\x08rule_ids\x18\x08 \x03(\tR\x07ruleIds\x12\x1b\n\tasset_ids\x18\t \x03(\tR\x08\x61ssetIds\x12\'\n\x0finclude_deleted\x18\n \x01(\x08R\x0eincludeDeleted\x12\x42\n\nasset_tags\x18\x0b \x01(\x0b\x32#.sift.common.type.v1.NamedResourcesR\tassetTagsB\x08\n\x06_limitB\x08\n\x06_orderB\x0b\n\t_order_by\"`\n\x13SearchRulesResponse\x12\x19\n\x05\x63ount\x18\x01 \x01(\rB\x03\xe0\x41\x02R\x05\x63ount\x12.\n\x05rules\x18\x02 \x03(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x05rules\"R\n\x0eGetRuleRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x01R\x06ruleId\x12\"\n\nclient_key\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tclientKey\"?\n\x0fGetRuleResponse\x12,\n\x04rule\x18\x01 \x01(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x04rule\"\\\n\x14\x42\x61tchGetRulesRequest\x12\x1e\n\x08rule_ids\x18\x01 \x03(\tB\x03\xe0\x41\x01R\x07ruleIds\x12$\n\x0b\x63lient_keys\x18\x02 \x03(\tB\x03\xe0\x41\x01R\nclientKeys\"G\n\x15\x42\x61tchGetRulesResponse\x12.\n\x05rules\x18\x01 \x03(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x05rules\"R\n\x11\x43reateRuleRequest\x12=\n\x06update\x18\x01 \x01(\x0b\x32 .sift.rules.v1.UpdateRuleRequestB\x03\xe0\x41\x02R\x06update\"2\n\x12\x43reateRuleResponse\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\"\xa1\x05\n\x11UpdateRuleRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tH\x00R\x06ruleId\x88\x01\x01\x12\x17\n\x04name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x04name\x12%\n\x0b\x64\x65scription\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x0b\x64\x65scription\x12 \n\x08\x61sset_id\x18\x04 \x01(\tB\x05\x18\x01\xe0\x41\x01R\x07\x61ssetId\x12$\n\nis_enabled\x18\x05 \x01(\x08\x42\x05\x18\x01\xe0\x41\x01R\tisEnabled\x12J\n\nconditions\x18\x06 \x03(\x0b\x32%.sift.rules.v1.UpdateConditionRequestB\x03\xe0\x41\x02R\nconditions\x12\'\n\x0forganization_id\x18\x07 \x01(\tR\x0eorganizationId\x12#\n\rversion_notes\x18\x08 \x01(\tR\x0cversionNotes\x12\"\n\nclient_key\x18\t \x01(\tH\x01R\tclientKey\x88\x01\x01\x12V\n\x13\x61sset_configuration\x18\n \x01(\x0b\x32%.sift.rules.v1.RuleAssetConfigurationR\x12\x61ssetConfiguration\x12R\n\x13\x63ontextual_channels\x18\x0b \x01(\x0b\x32!.sift.rules.v1.ContextualChannelsR\x12\x63ontextualChannels\x12\x1f\n\x0bis_external\x18\x0c \x01(\x08R\nisExternal\x12@\n\x08metadata\x18\r \x03(\x0b\x32\x1f.sift.metadata.v1.MetadataValueB\x03\xe0\x41\x02R\x08metadataB\n\n\x08_rule_idB\r\n\x0b_client_key\"\xf5\x01\n\x16UpdateConditionRequest\x12/\n\x11rule_condition_id\x18\x01 \x01(\tH\x00R\x0fruleConditionId\x88\x01\x01\x12K\n\nexpression\x18\x03 \x01(\x0b\x32&.sift.rules.v1.RuleConditionExpressionB\x03\xe0\x41\x02R\nexpression\x12\x41\n\x07\x61\x63tions\x18\x04 \x03(\x0b\x32\".sift.rules.v1.UpdateActionRequestB\x03\xe0\x41\x02R\x07\x61\x63tionsB\x14\n\x12_rule_condition_idJ\x04\x08\x02\x10\x03\"\xe7\x01\n\x13UpdateActionRequest\x12)\n\x0erule_action_id\x18\x01 \x01(\tH\x00R\x0cruleActionId\x88\x01\x01\x12?\n\x0b\x61\x63tion_type\x18\x02 \x01(\x0e\x32\x19.sift.rules.v1.ActionKindB\x03\xe0\x41\x02R\nactionType\x12Q\n\rconfiguration\x18\x03 \x01(\x0b\x32&.sift.rules.v1.RuleActionConfigurationB\x03\xe0\x41\x02R\rconfigurationB\x11\n\x0f_rule_action_id\"2\n\x12UpdateRuleResponse\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\"\x83\x02\n\x10ValidationResult\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x01R\x06ruleId\x12\"\n\nclient_key\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tclientKey\x12\x82\x01\n#asset_expression_validation_results\x18\x03 \x03(\x0b\x32..sift.rules.v1.AssetExpressionValidationResultB\x03\xe0\x41\x02R assetExpressionValidationResults\x12\x1e\n\x05\x65rror\x18\x04 \x01(\tB\x03\xe0\x41\x01H\x00R\x05\x65rror\x88\x01\x01\x42\x08\n\x06_error\"\xcb\x01\n\x17\x42\x61tchUpdateRulesRequest\x12;\n\x05rules\x18\x01 \x03(\x0b\x32 .sift.rules.v1.UpdateRuleRequestB\x03\xe0\x41\x02R\x05rules\x12(\n\rvalidate_only\x18\x02 \x01(\x08\x42\x03\xe0\x41\x01R\x0cvalidateOnly\x12I\n\x1eoverride_expression_validation\x18\x03 \x01(\x08\x42\x03\xe0\x41\x02R\x1coverrideExpressionValidation\"\x9d\x04\n\x18\x42\x61tchUpdateRulesResponse\x12\x1d\n\x07success\x18\x01 \x01(\x08\x42\x03\xe0\x41\x02R\x07success\x12\x33\n\x13rules_created_count\x18\x02 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesCreatedCount\x12\x33\n\x13rules_updated_count\x18\x03 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesUpdatedCount\x12(\n\rvalidate_only\x18\x04 \x01(\x08\x42\x03\xe0\x41\x02R\x0cvalidateOnly\x12S\n\x12validation_results\x18\x05 \x03(\x0b\x32\x1f.sift.rules.v1.ValidationResultB\x03\xe0\x41\x02R\x11validationResults\x12v\n\x18\x63reated_rule_identifiers\x18\x06 \x03(\x0b\x32\x37.sift.rules.v1.BatchUpdateRulesResponse.RuleIdentifiersB\x03\xe0\x41\x02R\x16\x63reatedRuleIdentifiers\x1a\x80\x01\n\x0fRuleIdentifiers\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12\x17\n\x04name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x04name\x12\'\n\nclient_key\x18\x03 \x01(\tB\x03\xe0\x41\x01H\x00R\tclientKey\x88\x01\x01\x42\r\n\x0b_client_key\"U\n\x11\x44\x65leteRuleRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x01R\x06ruleId\x12\"\n\nclient_key\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tclientKey\"\x14\n\x12\x44\x65leteRuleResponse\"_\n\x17\x42\x61tchDeleteRulesRequest\x12\x1e\n\x08rule_ids\x18\x01 \x03(\tB\x03\xe0\x41\x01R\x07ruleIds\x12$\n\x0b\x63lient_keys\x18\x02 \x03(\tB\x03\xe0\x41\x01R\nclientKeys\"\x1a\n\x18\x42\x61tchDeleteRulesResponse\"W\n\x13UndeleteRuleRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x01R\x06ruleId\x12\"\n\nclient_key\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tclientKey\"\x16\n\x14UndeleteRuleResponse\"a\n\x19\x42\x61tchUndeleteRulesRequest\x12\x1e\n\x08rule_ids\x18\x01 \x03(\tB\x03\xe0\x41\x01R\x07ruleIds\x12$\n\x0b\x63lient_keys\x18\x02 \x03(\tB\x03\xe0\x41\x01R\nclientKeys\"\x1c\n\x1a\x42\x61tchUndeleteRulesResponse\"C\n\x1dViewHumanFriendlyRulesRequest\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId:\x02\x18\x01\"H\n\x1eViewHumanFriendlyRulesResponse\x12\"\n\nrules_json\x18\x01 \x01(\tB\x03\xe0\x41\x02R\trulesJson:\x02\x18\x01\"\x97\x01\n\x1fUpdateHumanFriendlyRulesRequest\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\x12\"\n\nrules_json\x18\x02 \x01(\tB\x03\xe0\x41\x02R\trulesJson\x12,\n\x0forganization_id\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x0eorganizationId:\x02\x18\x01\"\x8c\x01\n UpdateHumanFriendlyRulesResponse\x12\x1d\n\x07success\x18\x01 \x01(\x08\x42\x03\xe0\x41\x02R\x07success\x12$\n\x0brules_count\x18\x02 \x01(\x05\x42\x03\xe0\x41\x02R\nrulesCount\x12\x1f\n\x08messages\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x08messages:\x02\x18\x01\"6\n\x14ViewJsonRulesRequest\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\";\n\x15ViewJsonRulesResponse\x12\"\n\nrules_json\x18\x01 \x01(\tB\x03\xe0\x41\x02R\trulesJson\"\x84\x01\n\x10JsonRulesRequest\x12\x1e\n\x08\x61sset_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x07\x61ssetId\x12\"\n\nrules_json\x18\x02 \x01(\tB\x03\xe0\x41\x02R\trulesJson\x12,\n\x0forganization_id\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x0eorganizationId\"\xc1\x02\n\x11JsonRulesResponse\x12\x1d\n\x07success\x18\x01 \x01(\x08\x42\x03\xe0\x41\x02R\x07success\x12/\n\x11total_rules_count\x18\x02 \x01(\x05\x42\x03\xe0\x41\x02R\x0ftotalRulesCount\x12\x33\n\x13rules_created_count\x18\x03 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesCreatedCount\x12\x33\n\x13rules_updated_count\x18\x04 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesUpdatedCount\x12\x33\n\x13rules_deleted_count\x18\x05 \x01(\x05\x42\x03\xe0\x41\x02R\x11rulesDeletedCount\x12*\n\x0e\x65rror_messages\x18\x06 \x01(\tH\x00R\rerrorMessages\x88\x01\x01\x42\x11\n\x0f_error_messages\"Z\n\x18ValidateJsonRulesRequest\x12>\n\x07request\x18\x01 \x01(\x0b\x32\x1f.sift.rules.v1.JsonRulesRequestB\x03\xe0\x41\x02R\x07request\"^\n\x19ValidateJsonRulesResponse\x12\x41\n\x08response\x18\x01 \x01(\x0b\x32 .sift.rules.v1.JsonRulesResponseB\x03\xe0\x41\x02R\x08response\"X\n\x16UpdateJsonRulesRequest\x12>\n\x07request\x18\x01 \x01(\x0b\x32\x1f.sift.rules.v1.JsonRulesRequestB\x03\xe0\x41\x02R\x07request\"\\\n\x17UpdateJsonRulesResponse\x12\x41\n\x08response\x18\x01 \x01(\x0b\x32 .sift.rules.v1.JsonRulesResponseB\x03\xe0\x41\x02R\x08response\"\x95\x01\n\x10ListRulesRequest\x12 \n\tpage_size\x18\x01 \x01(\rB\x03\xe0\x41\x01R\x08pageSize\x12\"\n\npage_token\x18\x02 \x01(\tB\x03\xe0\x41\x01R\tpageToken\x12\x1b\n\x06\x66ilter\x18\x03 \x01(\tB\x03\xe0\x41\x01R\x06\x66ilter\x12\x1e\n\x08order_by\x18\x04 \x01(\tB\x03\xe0\x41\x01R\x07orderBy\"k\n\x11ListRulesResponse\x12.\n\x05rules\x18\x01 \x03(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x05rules\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\x95\x01\n\x17ListRuleVersionsRequest\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12 \n\tpage_size\x18\x02 \x01(\rB\x03\xe0\x41\x01R\x08pageSize\x12\"\n\npage_token\x18\x03 \x01(\tB\x03\xe0\x41\x01R\tpageToken\x12\x16\n\x06\x66ilter\x18\x04 \x01(\tR\x06\x66ilter\"\x9a\x03\n\x0bRuleVersion\x12\x1c\n\x07rule_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x06ruleId\x12+\n\x0frule_version_id\x18\x02 \x01(\tB\x03\xe0\x41\x02R\rruleVersionId\x12\x1d\n\x07version\x18\x03 \x01(\tB\x03\xe0\x41\x02R\x07version\x12\x42\n\x0c\x63reated_date\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x0b\x63reatedDate\x12\x30\n\x12\x63reated_by_user_id\x18\x05 \x01(\tB\x03\xe0\x41\x02R\x0f\x63reatedByUserId\x12(\n\rversion_notes\x18\x06 \x01(\tB\x03\xe0\x41\x02R\x0cversionNotes\x12=\n\x18generated_change_message\x18\x07 \x01(\tB\x03\xe0\x41\x02R\x16generatedChangeMessage\x12\x42\n\x0c\x64\x65leted_date\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x01R\x0b\x64\x65letedDate\"\x88\x01\n\x18ListRuleVersionsResponse\x12\x44\n\rrule_versions\x18\x01 \x03(\x0b\x32\x1a.sift.rules.v1.RuleVersionB\x03\xe0\x41\x02R\x0cruleVersions\x12&\n\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"D\n\x15GetRuleVersionRequest\x12+\n\x0frule_version_id\x18\x01 \x01(\tB\x03\xe0\x41\x02R\rruleVersionId\"F\n\x16GetRuleVersionResponse\x12,\n\x04rule\x18\x01 \x01(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x04rule\"L\n\x1b\x42\x61tchGetRuleVersionsRequest\x12-\n\x10rule_version_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x0eruleVersionIds\"N\n\x1c\x42\x61tchGetRuleVersionsResponse\x12.\n\x05rules\x18\x01 \x03(\x0b\x32\x13.sift.rules.v1.RuleB\x03\xe0\x41\x02R\x05rules\"\xf4\x01\n\x17RuleConditionExpression\x12r\n\x19single_channel_comparison\x18\x01 \x01(\x0b\x32\x30.sift.rules.v1.SingleChannelComparisonExpressionB\x02\x18\x01H\x00R\x17singleChannelComparison\x12W\n\x12\x63\x61lculated_channel\x18\x02 \x01(\x0b\x32&.sift.rules.v1.CalculatedChannelConfigH\x00R\x11\x63\x61lculatedChannelB\x0c\n\nexpression\"\xcb\x02\n!SingleChannelComparisonExpression\x12\x30\n\x11\x63hannel_component\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x10\x63hannelComponent\x12&\n\x0c\x63hannel_name\x18\x02 \x01(\tB\x03\xe0\x41\x02R\x0b\x63hannelName\x12G\n\ncomparator\x18\x03 \x01(\x0e\x32\".sift.rules.v1.ConditionComparatorB\x03\xe0\x41\x02R\ncomparator\x12\x18\n\x06\x64ouble\x18\x04 \x01(\x01H\x00R\x06\x64ouble\x12\x18\n\x06string\x18\x05 \x01(\tH\x00R\x06string\x12\x42\n\nlast_value\x18\x06 \x01(\x0b\x32!.sift.rules.v1.LastValueThresholdH\x00R\tlastValueB\x0b\n\tthreshold\"\x14\n\x12LastValueThreshold\"\xfb\x02\n\x17\x43\x61lculatedChannelConfig\x12q\n\x12\x63hannel_references\x18\x01 \x03(\x0b\x32=.sift.rules.v1.CalculatedChannelConfig.ChannelReferencesEntryB\x03\xe0\x41\x02R\x11\x63hannelReferences\x12#\n\nexpression\x18\x02 \x01(\tB\x03\xe0\x41\x02R\nexpression\x12\x61\n\x15\x66unction_dependencies\x18\x03 \x03(\x0b\x32\'.sift.common.type.v1.FunctionDependencyB\x03\xe0\x41\x01R\x14\x66unctionDependencies\x1a\x65\n\x16\x43hannelReferencesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x35\n\x05value\x18\x02 \x01(\x0b\x32\x1f.sift.rules.v1.ChannelReferenceR\x05value:\x02\x38\x01\"N\n\x10\x43hannelReference\x12\x17\n\x04name\x18\x01 \x01(\tB\x03\xe0\x41\x02R\x04name\x12!\n\tcomponent\x18\x02 \x01(\tB\x03\xe0\x41\x02R\tcomponent\"\xd0\x01\n\x17RuleActionConfiguration\x12T\n\x0cnotification\x18\x01 \x01(\x0b\x32..sift.rules.v1.NotificationActionConfigurationH\x00R\x0cnotification\x12N\n\nannotation\x18\x02 \x01(\x0b\x32,.sift.rules.v1.AnnotationActionConfigurationH\x00R\nannotationB\x0f\n\rconfiguration\"T\n\x1fNotificationActionConfiguration\x12\x31\n\x12recipient_user_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x10recipientUserIds\"\x94\x02\n\x1d\x41nnotationActionConfiguration\x12\x1c\n\x07tag_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x06tagIds\x12L\n\x0f\x61nnotation_type\x18\x02 \x01(\x0e\x32#.sift.annotations.v1.AnnotationTypeR\x0e\x61nnotationType\x12\x32\n\x13\x61ssigned_to_user_id\x18\x03 \x01(\tH\x00R\x10\x61ssignedToUserId\x88\x01\x01\x12;\n\x08metadata\x18\x04 \x03(\x0b\x32\x1f.sift.metadata.v1.MetadataValueR\x08metadataB\x16\n\x14_assigned_to_user_id\"\x8e\x02\n\x14\x45valuateRulesRequest\x12\x1e\n\x08rule_ids\x18\x01 \x03(\tB\x03\xe0\x41\x02R\x07ruleIds\x12X\n\x12\x61nnotation_options\x18\x02 \x01(\x0b\x32).sift.rules.v1.EvaluatedAnnotationOptionsR\x11\x61nnotationOptions\x12\x17\n\x06run_id\x18\x03 \x01(\tH\x00R\x05runId\x12>\n\ntime_range\x18\x04 \x01(\x0b\x32\x1d.sift.rules.v1.TimeRangeQueryH\x00R\ttimeRange\x12\x17\n\x07\x64ry_run\x18\x05 \x01(\x08R\x06\x64ryRun:\x02\x18\x01\x42\x06\n\x04time\"5\n\x1a\x45valuatedAnnotationOptions\x12\x17\n\x07tag_ids\x18\x01 \x03(\tR\x06tagIds\"\x82\x01\n\x0eTimeRangeQuery\x12\x39\n\nstart_time\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tstartTime\x12\x35\n\x08\x65nd_time\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x07\x65ndTime\"\xfd\x01\n\x15\x45valuateRulesResponse\x12\x38\n\x18\x63reated_annotation_count\x18\x01 \x01(\x05R\x16\x63reatedAnnotationCount\x12O\n\x13\x64ry_run_annotations\x18\x02 \x03(\x0b\x32\x1f.sift.rules.v1.DryRunAnnotationR\x11\x64ryRunAnnotations\x12\x1a\n\x06job_id\x18\x03 \x01(\tH\x00R\x05jobId\x88\x01\x01\x12 \n\treport_id\x18\x04 \x01(\tH\x01R\x08reportId\x88\x01\x01:\x02\x18\x01\x42\t\n\x07_job_idB\x0c\n\n_report_id\"\xf7\x01\n\x10\x44ryRunAnnotation\x12!\n\x0c\x63ondition_id\x18\x01 \x01(\tR\x0b\x63onditionId\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12>\n\nstart_time\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\tstartTime\x12:\n\x08\x65nd_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampB\x03\xe0\x41\x02R\x07\x65ndTime\x12\x30\n\x14\x63ondition_version_id\x18\x05 \x01(\tR\x12\x63onditionVersionId*\\\n\x0bSearchOrder\x12 \n\x18SEARCH_ORDER_UNSPECIFIED\x10\x00\x1a\x02\x08\x01\x12\x14\n\x10SEARCH_ORDER_ASC\x10\x01\x12\x15\n\x11SEARCH_ORDER_DESC\x10\x02*\\\n\nActionKind\x12\x1f\n\x17\x41\x43TION_KIND_UNSPECIFIED\x10\x00\x1a\x02\x08\x01\x12\x10\n\x0cNOTIFICATION\x10\x01\x12\x0e\n\nANNOTATION\x10\x02\x12\x0b\n\x07WEBHOOK\x10\x03*\xad\x01\n\x13\x43onditionComparator\x12(\n CONDITION_COMPARATOR_UNSPECIFIED\x10\x00\x1a\x02\x08\x01\x12\r\n\tLESS_THAN\x10\x01\x12\x16\n\x12LESS_THAN_OR_EQUAL\x10\x02\x12\x10\n\x0cGREATER_THAN\x10\x03\x12\x19\n\x15GREATER_THAN_OR_EQUAL\x10\x04\x12\t\n\x05\x45QUAL\x10\x05\x12\r\n\tNOT_EQUAL\x10\x06\x32\xd0 \n\x0bRuleService\x12\xb9\x01\n\x0bSearchRules\x12!.sift.rules.v1.SearchRulesRequest\x1a\".sift.rules.v1.SearchRulesResponse\"c\x92\x41\x41\x12\x0bSearchRules\x1a\x32Queries rules based on provided search parameters.\x82\xd3\xe4\x93\x02\x19\"\x14/api/v1/rules/search:\x01*\x12\x94\x01\n\x07GetRule\x12\x1d.sift.rules.v1.GetRuleRequest\x1a\x1e.sift.rules.v1.GetRuleResponse\"J\x92\x41\x32\x12\x07GetRule\x1a\'Retrieves the latest version of a rule.\x82\xd3\xe4\x93\x02\x0f\x12\r/api/v1/rules\x12\xaa\x01\n\rBatchGetRules\x12#.sift.rules.v1.BatchGetRulesRequest\x1a$.sift.rules.v1.BatchGetRulesResponse\"N\x92\x41*\x12\rBatchGetRules\x1a\x19Retrieves multiple rules.\x82\xd3\xe4\x93\x02\x1b\"\x16/api/v1/rules:batchGet:\x01*\x12\x8b\x01\n\nCreateRule\x12 .sift.rules.v1.CreateRuleRequest\x1a!.sift.rules.v1.CreateRuleResponse\"8\x92\x41\x1d\x12\nCreateRule\x1a\x0f\x43reates a rule.\x82\xd3\xe4\x93\x02\x12\"\r/api/v1/rules:\x01*\x12\x95\x01\n\nUpdateRule\x12 .sift.rules.v1.UpdateRuleRequest\x1a!.sift.rules.v1.UpdateRuleResponse\"B\x92\x41\'\x12\nUpdateRule\x1a\x19Updates an existing rule.\x82\xd3\xe4\x93\x02\x12\x1a\r/api/v1/rules:\x01*\x12\xda\x01\n\x10\x42\x61tchUpdateRules\x12&.sift.rules.v1.BatchUpdateRulesRequest\x1a\'.sift.rules.v1.BatchUpdateRulesResponse\"u\x92\x41N\x12\x10\x42\x61tchUpdateRules\x1a:Updates existing rules or creates rules that do not exist.\x82\xd3\xe4\x93\x02\x1e\x1a\x19/api/v1/rules:batchUpdate:\x01*\x12\x92\x01\n\nDeleteRule\x12 .sift.rules.v1.DeleteRuleRequest\x1a!.sift.rules.v1.DeleteRuleResponse\"?\x92\x41\x1d\x12\nDeleteRule\x1a\x0f\x44\x65letes a rule.\x82\xd3\xe4\x93\x02\x19\"\x14/api/v1/rules/delete:\x01*\x12\xb7\x01\n\x10\x42\x61tchDeleteRules\x12&.sift.rules.v1.BatchDeleteRulesRequest\x1a\'.sift.rules.v1.BatchDeleteRulesResponse\"R\x92\x41+\x12\x10\x42\x61tchDeleteRules\x1a\x17\x44\x65letes multiple rules.\x82\xd3\xe4\x93\x02\x1e\"\x19/api/v1/rules/batchDelete:\x01*\x12\x9e\x01\n\x0cUndeleteRule\x12\".sift.rules.v1.UndeleteRuleRequest\x1a#.sift.rules.v1.UndeleteRuleResponse\"E\x92\x41!\x12\x0cUndeleteRule\x1a\x11Undeletes a rule.\x82\xd3\xe4\x93\x02\x1b\"\x16/api/v1/rules/undelete:\x01*\x12\xc3\x01\n\x12\x42\x61tchUndeleteRules\x12(.sift.rules.v1.BatchUndeleteRulesRequest\x1a).sift.rules.v1.BatchUndeleteRulesResponse\"X\x92\x41/\x12\x12\x42\x61tchUndeleteRules\x1a\x19Undeletes multiple rules.\x82\xd3\xe4\x93\x02 \"\x1b/api/v1/rules/batchUndelete:\x01*\x12\xdf\x01\n\rEvaluateRules\x12#.sift.rules.v1.EvaluateRulesRequest\x1a$.sift.rules.v1.EvaluateRulesResponse\"\x82\x01\x88\x02\x01\x92\x41[\x12\rEvaluateRules\x1aJEvaluates the provided rules and generate annotations based on the result.\x82\xd3\xe4\x93\x02\x1b\"\x16/api/v1/rules/evaluate:\x01*\x12\x84\x02\n\x16ViewHumanFriendlyRules\x12,.sift.rules.v1.ViewHumanFriendlyRulesRequest\x1a-.sift.rules.v1.ViewHumanFriendlyRulesResponse\"\x8c\x01\x88\x02\x01\x92\x41_\x12\x16ViewHumanFriendlyRules\x1a\x45Retrieve a JSON object containing all of the rules for a given asset.\x82\xd3\xe4\x93\x02!\x12\x1f/api/v1/rules:viewHumanFriendly\x12\xd6\x01\n\rViewJsonRules\x12#.sift.rules.v1.ViewJsonRulesRequest\x1a$.sift.rules.v1.ViewJsonRulesResponse\"z\x88\x02\x01\x92\x41V\x12\rViewJsonRules\x1a\x45Retrieve a JSON object containing all of the rules for a given asset.\x82\xd3\xe4\x93\x02\x18\x12\x16/api/v1/rules:viewJson\x12\x94\x02\n\x18UpdateHumanFriendlyRules\x12..sift.rules.v1.UpdateHumanFriendlyRulesRequest\x1a/.sift.rules.v1.UpdateHumanFriendlyRulesResponse\"\x96\x01\x88\x02\x01\x92\x41\x64\x12\x18UpdateHumanFriendlyRules\x1aHBatch update rules given the `rules_json` which is a JSON list of rules.\x82\xd3\xe4\x93\x02&\"!/api/v1/rules:updateHumanFriendly:\x01*\x12\x80\x02\n\x11ValidateJsonRules\x12\'.sift.rules.v1.ValidateJsonRulesRequest\x1a(.sift.rules.v1.ValidateJsonRulesResponse\"\x97\x01\x88\x02\x01\x92\x41l\x12\x11ValidateJsonRules\x1aWValidate a batch update for rules given the `rules_json` which is a JSON list of rules.\x82\xd3\xe4\x93\x02\x1f\"\x1a/api/v1/rules:validateJson:\x01*\x12\xe7\x01\n\x0fUpdateJsonRules\x12%.sift.rules.v1.UpdateJsonRulesRequest\x1a&.sift.rules.v1.UpdateJsonRulesResponse\"\x84\x01\x88\x02\x01\x92\x41[\x12\x0fUpdateJsonRules\x1aHBatch update rules given the `rules_json` which is a JSON list of rules.\x82\xd3\xe4\x93\x02\x1d\"\x18/api/v1/rules:updateJson:\x01*\x12\x94\x01\n\tListRules\x12\x1f.sift.rules.v1.ListRulesRequest\x1a .sift.rules.v1.ListRulesResponse\"D\x92\x41\'\x12\tListRules\x1a\x1aRetrieves a list of rules.\x82\xd3\xe4\x93\x02\x14\x12\x12/api/v1/rules:list\x12\xd9\x01\n\x10ListRuleVersions\x12&.sift.rules.v1.ListRuleVersionsRequest\x1a\'.sift.rules.v1.ListRuleVersionsResponse\"t\x92\x41I\x12\x10ListRuleVersions\x1a\x35Retrieves a list of rule versions for the given rule.\x82\xd3\xe4\x93\x02\"\x12 /api/v1/rules/{rule_id}/versions\x12\xb8\x01\n\x0eGetRuleVersion\x12$.sift.rules.v1.GetRuleVersionRequest\x1a%.sift.rules.v1.GetRuleVersionResponse\"Y\x92\x41\x39\x12\x0eGetRuleVersion\x1a\'Retrieves a specific version of a rule.\x82\xd3\xe4\x93\x02\x17\x12\x15/api/v1/rules:version\x12\xdf\x01\n\x14\x42\x61tchGetRuleVersions\x12*.sift.rules.v1.BatchGetRuleVersionsRequest\x1a+.sift.rules.v1.BatchGetRuleVersionsResponse\"n\x92\x41\x42\x12\x14\x42\x61tchGetRuleVersions\x1a*Retrieves multiple rules by rule versions.\x82\xd3\xe4\x93\x02#\"\x1e/api/v1/rules:batchGetVersions:\x01*\x1a\xb1\x01\x92\x41\xad\x01\x12\x30Service to programmatically interact with rules.\x1ay\n\x1fRead more about what rules are.\x12Vhttps://customer.support.siftstack.com/servicedesk/customer/portal/2/article/265421102B\x88\x01\n\x11\x63om.sift.rules.v1B\nRulesProtoP\x01\xa2\x02\x03SRX\xaa\x02\rSift.Rules.V1\xca\x02\rSift\\Rules\\V1\xe2\x02\x19Sift\\Rules\\V1\\GPBMetadata\xea\x02\x0fSift::Rules::V1\x92\x41\x10\x12\x0e\n\x0cRule Serviceb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -69,6 +70,8 @@ _globals['_RULE'].fields_by_name['deleted_date']._serialized_options = b'\340A\001' _globals['_RULE'].fields_by_name['is_external']._loaded_options = None _globals['_RULE'].fields_by_name['is_external']._serialized_options = b'\340A\002' + _globals['_RULE'].fields_by_name['metadata']._loaded_options = None + _globals['_RULE'].fields_by_name['metadata']._serialized_options = b'\340A\002' _globals['_RULECONDITION'].fields_by_name['rule_condition_id']._loaded_options = None _globals['_RULECONDITION'].fields_by_name['rule_condition_id']._serialized_options = b'\340A\002' _globals['_RULECONDITION'].fields_by_name['rule_id']._loaded_options = None @@ -142,9 +145,11 @@ _globals['_UPDATERULEREQUEST'].fields_by_name['asset_id']._loaded_options = None _globals['_UPDATERULEREQUEST'].fields_by_name['asset_id']._serialized_options = b'\030\001\340A\001' _globals['_UPDATERULEREQUEST'].fields_by_name['is_enabled']._loaded_options = None - _globals['_UPDATERULEREQUEST'].fields_by_name['is_enabled']._serialized_options = b'\340A\002' + _globals['_UPDATERULEREQUEST'].fields_by_name['is_enabled']._serialized_options = b'\030\001\340A\001' _globals['_UPDATERULEREQUEST'].fields_by_name['conditions']._loaded_options = None _globals['_UPDATERULEREQUEST'].fields_by_name['conditions']._serialized_options = b'\340A\002' + _globals['_UPDATERULEREQUEST'].fields_by_name['metadata']._loaded_options = None + _globals['_UPDATERULEREQUEST'].fields_by_name['metadata']._serialized_options = b'\340A\002' _globals['_UPDATECONDITIONREQUEST'].fields_by_name['expression']._loaded_options = None _globals['_UPDATECONDITIONREQUEST'].fields_by_name['expression']._serialized_options = b'\340A\002' _globals['_UPDATECONDITIONREQUEST'].fields_by_name['actions']._loaded_options = None @@ -317,16 +322,6 @@ _globals['_CHANNELREFERENCE'].fields_by_name['name']._serialized_options = b'\340A\002' _globals['_CHANNELREFERENCE'].fields_by_name['component']._loaded_options = None _globals['_CHANNELREFERENCE'].fields_by_name['component']._serialized_options = b'\340A\002' - _globals['_PYTHONCHANNELREFERENCE'].fields_by_name['reference']._loaded_options = None - _globals['_PYTHONCHANNELREFERENCE'].fields_by_name['reference']._serialized_options = b'\340A\002' - _globals['_PYTHONCHANNELREFERENCE'].fields_by_name['name']._loaded_options = None - _globals['_PYTHONCHANNELREFERENCE'].fields_by_name['name']._serialized_options = b'\340A\002' - _globals['_PYTHONCODE'].fields_by_name['channel_references']._loaded_options = None - _globals['_PYTHONCODE'].fields_by_name['channel_references']._serialized_options = b'\340A\002' - _globals['_PYTHONCODE'].fields_by_name['code']._loaded_options = None - _globals['_PYTHONCODE'].fields_by_name['code']._serialized_options = b'\340A\002' - _globals['_PYTHONCODE'].fields_by_name['dependencies']._loaded_options = None - _globals['_PYTHONCODE'].fields_by_name['dependencies']._serialized_options = b'\340A\001' _globals['_NOTIFICATIONACTIONCONFIGURATION'].fields_by_name['recipient_user_ids']._loaded_options = None _globals['_NOTIFICATIONACTIONCONFIGURATION'].fields_by_name['recipient_user_ids']._serialized_options = b'\340A\002' _globals['_ANNOTATIONACTIONCONFIGURATION'].fields_by_name['tag_ids']._loaded_options = None @@ -383,146 +378,142 @@ _globals['_RULESERVICE'].methods_by_name['GetRuleVersion']._serialized_options = b'\222A9\022\016GetRuleVersion\032\'Retrieves a specific version of a rule.\202\323\344\223\002\027\022\025/api/v1/rules:version' _globals['_RULESERVICE'].methods_by_name['BatchGetRuleVersions']._loaded_options = None _globals['_RULESERVICE'].methods_by_name['BatchGetRuleVersions']._serialized_options = b'\222AB\022\024BatchGetRuleVersions\032*Retrieves multiple rules by rule versions.\202\323\344\223\002#\"\036/api/v1/rules:batchGetVersions:\001*' - _globals['_SEARCHORDER']._serialized_start=11853 - _globals['_SEARCHORDER']._serialized_end=11945 - _globals['_ACTIONKIND']._serialized_start=11947 - _globals['_ACTIONKIND']._serialized_end=12039 - _globals['_CONDITIONCOMPARATOR']._serialized_start=12042 - _globals['_CONDITIONCOMPARATOR']._serialized_end=12215 - _globals['_RULE']._serialized_start=325 - _globals['_RULE']._serialized_end=1246 - _globals['_RULECONDITION']._serialized_start=1249 - _globals['_RULECONDITION']._serialized_end=1788 - _globals['_RULEACTION']._serialized_start=1791 - _globals['_RULEACTION']._serialized_end=2341 - _globals['_RULEASSETCONFIGURATION']._serialized_start=2343 - _globals['_RULEASSETCONFIGURATION']._serialized_end=2421 - _globals['_CONTEXTUALCHANNELS']._serialized_start=2423 - _globals['_CONTEXTUALCHANNELS']._serialized_end=2509 - _globals['_ASSETEXPRESSIONVALIDATIONRESULT']._serialized_start=2512 - _globals['_ASSETEXPRESSIONVALIDATIONRESULT']._serialized_end=2694 - _globals['_SEARCHRULESREQUEST']._serialized_start=2697 - _globals['_SEARCHRULESREQUEST']._serialized_end=3151 - _globals['_SEARCHRULESRESPONSE']._serialized_start=3153 - _globals['_SEARCHRULESRESPONSE']._serialized_end=3249 - _globals['_GETRULEREQUEST']._serialized_start=3251 - _globals['_GETRULEREQUEST']._serialized_end=3333 - _globals['_GETRULERESPONSE']._serialized_start=3335 - _globals['_GETRULERESPONSE']._serialized_end=3398 - _globals['_BATCHGETRULESREQUEST']._serialized_start=3400 - _globals['_BATCHGETRULESREQUEST']._serialized_end=3492 - _globals['_BATCHGETRULESRESPONSE']._serialized_start=3494 - _globals['_BATCHGETRULESRESPONSE']._serialized_end=3565 - _globals['_CREATERULEREQUEST']._serialized_start=3567 - _globals['_CREATERULEREQUEST']._serialized_end=3649 - _globals['_CREATERULERESPONSE']._serialized_start=3651 - _globals['_CREATERULERESPONSE']._serialized_end=3701 - _globals['_UPDATERULEREQUEST']._serialized_start=3704 - _globals['_UPDATERULEREQUEST']._serialized_end=4309 - _globals['_UPDATECONDITIONREQUEST']._serialized_start=4312 - _globals['_UPDATECONDITIONREQUEST']._serialized_end=4557 - _globals['_UPDATEACTIONREQUEST']._serialized_start=4560 - _globals['_UPDATEACTIONREQUEST']._serialized_end=4791 - _globals['_UPDATERULERESPONSE']._serialized_start=4793 - _globals['_UPDATERULERESPONSE']._serialized_end=4843 - _globals['_VALIDATIONRESULT']._serialized_start=4846 - _globals['_VALIDATIONRESULT']._serialized_end=5105 - _globals['_BATCHUPDATERULESREQUEST']._serialized_start=5108 - _globals['_BATCHUPDATERULESREQUEST']._serialized_end=5311 - _globals['_BATCHUPDATERULESRESPONSE']._serialized_start=5314 - _globals['_BATCHUPDATERULESRESPONSE']._serialized_end=5855 - _globals['_BATCHUPDATERULESRESPONSE_RULEIDENTIFIERS']._serialized_start=5727 - _globals['_BATCHUPDATERULESRESPONSE_RULEIDENTIFIERS']._serialized_end=5855 - _globals['_DELETERULEREQUEST']._serialized_start=5857 - _globals['_DELETERULEREQUEST']._serialized_end=5942 - _globals['_DELETERULERESPONSE']._serialized_start=5944 - _globals['_DELETERULERESPONSE']._serialized_end=5964 - _globals['_BATCHDELETERULESREQUEST']._serialized_start=5966 - _globals['_BATCHDELETERULESREQUEST']._serialized_end=6061 - _globals['_BATCHDELETERULESRESPONSE']._serialized_start=6063 - _globals['_BATCHDELETERULESRESPONSE']._serialized_end=6089 - _globals['_UNDELETERULEREQUEST']._serialized_start=6091 - _globals['_UNDELETERULEREQUEST']._serialized_end=6178 - _globals['_UNDELETERULERESPONSE']._serialized_start=6180 - _globals['_UNDELETERULERESPONSE']._serialized_end=6202 - _globals['_BATCHUNDELETERULESREQUEST']._serialized_start=6204 - _globals['_BATCHUNDELETERULESREQUEST']._serialized_end=6301 - _globals['_BATCHUNDELETERULESRESPONSE']._serialized_start=6303 - _globals['_BATCHUNDELETERULESRESPONSE']._serialized_end=6331 - _globals['_VIEWHUMANFRIENDLYRULESREQUEST']._serialized_start=6333 - _globals['_VIEWHUMANFRIENDLYRULESREQUEST']._serialized_end=6400 - _globals['_VIEWHUMANFRIENDLYRULESRESPONSE']._serialized_start=6402 - _globals['_VIEWHUMANFRIENDLYRULESRESPONSE']._serialized_end=6474 - _globals['_UPDATEHUMANFRIENDLYRULESREQUEST']._serialized_start=6477 - _globals['_UPDATEHUMANFRIENDLYRULESREQUEST']._serialized_end=6628 - _globals['_UPDATEHUMANFRIENDLYRULESRESPONSE']._serialized_start=6631 - _globals['_UPDATEHUMANFRIENDLYRULESRESPONSE']._serialized_end=6771 - _globals['_VIEWJSONRULESREQUEST']._serialized_start=6773 - _globals['_VIEWJSONRULESREQUEST']._serialized_end=6827 - _globals['_VIEWJSONRULESRESPONSE']._serialized_start=6829 - _globals['_VIEWJSONRULESRESPONSE']._serialized_end=6888 - _globals['_JSONRULESREQUEST']._serialized_start=6891 - _globals['_JSONRULESREQUEST']._serialized_end=7023 - _globals['_JSONRULESRESPONSE']._serialized_start=7026 - _globals['_JSONRULESRESPONSE']._serialized_end=7347 - _globals['_VALIDATEJSONRULESREQUEST']._serialized_start=7349 - _globals['_VALIDATEJSONRULESREQUEST']._serialized_end=7439 - _globals['_VALIDATEJSONRULESRESPONSE']._serialized_start=7441 - _globals['_VALIDATEJSONRULESRESPONSE']._serialized_end=7535 - _globals['_UPDATEJSONRULESREQUEST']._serialized_start=7537 - _globals['_UPDATEJSONRULESREQUEST']._serialized_end=7625 - _globals['_UPDATEJSONRULESRESPONSE']._serialized_start=7627 - _globals['_UPDATEJSONRULESRESPONSE']._serialized_end=7719 - _globals['_LISTRULESREQUEST']._serialized_start=7722 - _globals['_LISTRULESREQUEST']._serialized_end=7871 - _globals['_LISTRULESRESPONSE']._serialized_start=7873 - _globals['_LISTRULESRESPONSE']._serialized_end=7980 - _globals['_LISTRULEVERSIONSREQUEST']._serialized_start=7983 - _globals['_LISTRULEVERSIONSREQUEST']._serialized_end=8132 - _globals['_RULEVERSION']._serialized_start=8135 - _globals['_RULEVERSION']._serialized_end=8545 - _globals['_LISTRULEVERSIONSRESPONSE']._serialized_start=8548 - _globals['_LISTRULEVERSIONSRESPONSE']._serialized_end=8684 - _globals['_GETRULEVERSIONREQUEST']._serialized_start=8686 - _globals['_GETRULEVERSIONREQUEST']._serialized_end=8754 - _globals['_GETRULEVERSIONRESPONSE']._serialized_start=8756 - _globals['_GETRULEVERSIONRESPONSE']._serialized_end=8826 - _globals['_BATCHGETRULEVERSIONSREQUEST']._serialized_start=8828 - _globals['_BATCHGETRULEVERSIONSREQUEST']._serialized_end=8904 - _globals['_BATCHGETRULEVERSIONSRESPONSE']._serialized_start=8906 - _globals['_BATCHGETRULEVERSIONSRESPONSE']._serialized_end=8984 - _globals['_RULECONDITIONEXPRESSION']._serialized_start=8987 - _globals['_RULECONDITIONEXPRESSION']._serialized_end=9293 - _globals['_SINGLECHANNELCOMPARISONEXPRESSION']._serialized_start=9296 - _globals['_SINGLECHANNELCOMPARISONEXPRESSION']._serialized_end=9627 - _globals['_LASTVALUETHRESHOLD']._serialized_start=9629 - _globals['_LASTVALUETHRESHOLD']._serialized_end=9649 - _globals['_CALCULATEDCHANNELCONFIG']._serialized_start=9652 - _globals['_CALCULATEDCHANNELCONFIG']._serialized_end=10031 - _globals['_CALCULATEDCHANNELCONFIG_CHANNELREFERENCESENTRY']._serialized_start=9930 - _globals['_CALCULATEDCHANNELCONFIG_CHANNELREFERENCESENTRY']._serialized_end=10031 - _globals['_CHANNELREFERENCE']._serialized_start=10033 - _globals['_CHANNELREFERENCE']._serialized_end=10111 - _globals['_PYTHONCHANNELREFERENCE']._serialized_start=10113 - _globals['_PYTHONCHANNELREFERENCE']._serialized_end=10197 - _globals['_PYTHONCODE']._serialized_start=10200 - _globals['_PYTHONCODE']._serialized_end=10369 - _globals['_RULEACTIONCONFIGURATION']._serialized_start=10372 - _globals['_RULEACTIONCONFIGURATION']._serialized_end=10580 - _globals['_NOTIFICATIONACTIONCONFIGURATION']._serialized_start=10582 - _globals['_NOTIFICATIONACTIONCONFIGURATION']._serialized_end=10666 - _globals['_ANNOTATIONACTIONCONFIGURATION']._serialized_start=10669 - _globals['_ANNOTATIONACTIONCONFIGURATION']._serialized_end=10884 - _globals['_EVALUATERULESREQUEST']._serialized_start=10887 - _globals['_EVALUATERULESREQUEST']._serialized_end=11157 - _globals['_EVALUATEDANNOTATIONOPTIONS']._serialized_start=11159 - _globals['_EVALUATEDANNOTATIONOPTIONS']._serialized_end=11212 - _globals['_TIMERANGEQUERY']._serialized_start=11215 - _globals['_TIMERANGEQUERY']._serialized_end=11345 - _globals['_EVALUATERULESRESPONSE']._serialized_start=11348 - _globals['_EVALUATERULESRESPONSE']._serialized_end=11601 - _globals['_DRYRUNANNOTATION']._serialized_start=11604 - _globals['_DRYRUNANNOTATION']._serialized_end=11851 - _globals['_RULESERVICE']._serialized_start=12218 - _globals['_RULESERVICE']._serialized_end=16394 + _globals['_SEARCHORDER']._serialized_start=11761 + _globals['_SEARCHORDER']._serialized_end=11853 + _globals['_ACTIONKIND']._serialized_start=11855 + _globals['_ACTIONKIND']._serialized_end=11947 + _globals['_CONDITIONCOMPARATOR']._serialized_start=11950 + _globals['_CONDITIONCOMPARATOR']._serialized_end=12123 + _globals['_RULE']._serialized_start=358 + _globals['_RULE']._serialized_end=1345 + _globals['_RULECONDITION']._serialized_start=1348 + _globals['_RULECONDITION']._serialized_end=1887 + _globals['_RULEACTION']._serialized_start=1890 + _globals['_RULEACTION']._serialized_end=2440 + _globals['_RULEASSETCONFIGURATION']._serialized_start=2442 + _globals['_RULEASSETCONFIGURATION']._serialized_end=2520 + _globals['_CONTEXTUALCHANNELS']._serialized_start=2522 + _globals['_CONTEXTUALCHANNELS']._serialized_end=2608 + _globals['_ASSETEXPRESSIONVALIDATIONRESULT']._serialized_start=2611 + _globals['_ASSETEXPRESSIONVALIDATIONRESULT']._serialized_end=2793 + _globals['_SEARCHRULESREQUEST']._serialized_start=2796 + _globals['_SEARCHRULESREQUEST']._serialized_end=3250 + _globals['_SEARCHRULESRESPONSE']._serialized_start=3252 + _globals['_SEARCHRULESRESPONSE']._serialized_end=3348 + _globals['_GETRULEREQUEST']._serialized_start=3350 + _globals['_GETRULEREQUEST']._serialized_end=3432 + _globals['_GETRULERESPONSE']._serialized_start=3434 + _globals['_GETRULERESPONSE']._serialized_end=3497 + _globals['_BATCHGETRULESREQUEST']._serialized_start=3499 + _globals['_BATCHGETRULESREQUEST']._serialized_end=3591 + _globals['_BATCHGETRULESRESPONSE']._serialized_start=3593 + _globals['_BATCHGETRULESRESPONSE']._serialized_end=3664 + _globals['_CREATERULEREQUEST']._serialized_start=3666 + _globals['_CREATERULEREQUEST']._serialized_end=3748 + _globals['_CREATERULERESPONSE']._serialized_start=3750 + _globals['_CREATERULERESPONSE']._serialized_end=3800 + _globals['_UPDATERULEREQUEST']._serialized_start=3803 + _globals['_UPDATERULEREQUEST']._serialized_end=4476 + _globals['_UPDATECONDITIONREQUEST']._serialized_start=4479 + _globals['_UPDATECONDITIONREQUEST']._serialized_end=4724 + _globals['_UPDATEACTIONREQUEST']._serialized_start=4727 + _globals['_UPDATEACTIONREQUEST']._serialized_end=4958 + _globals['_UPDATERULERESPONSE']._serialized_start=4960 + _globals['_UPDATERULERESPONSE']._serialized_end=5010 + _globals['_VALIDATIONRESULT']._serialized_start=5013 + _globals['_VALIDATIONRESULT']._serialized_end=5272 + _globals['_BATCHUPDATERULESREQUEST']._serialized_start=5275 + _globals['_BATCHUPDATERULESREQUEST']._serialized_end=5478 + _globals['_BATCHUPDATERULESRESPONSE']._serialized_start=5481 + _globals['_BATCHUPDATERULESRESPONSE']._serialized_end=6022 + _globals['_BATCHUPDATERULESRESPONSE_RULEIDENTIFIERS']._serialized_start=5894 + _globals['_BATCHUPDATERULESRESPONSE_RULEIDENTIFIERS']._serialized_end=6022 + _globals['_DELETERULEREQUEST']._serialized_start=6024 + _globals['_DELETERULEREQUEST']._serialized_end=6109 + _globals['_DELETERULERESPONSE']._serialized_start=6111 + _globals['_DELETERULERESPONSE']._serialized_end=6131 + _globals['_BATCHDELETERULESREQUEST']._serialized_start=6133 + _globals['_BATCHDELETERULESREQUEST']._serialized_end=6228 + _globals['_BATCHDELETERULESRESPONSE']._serialized_start=6230 + _globals['_BATCHDELETERULESRESPONSE']._serialized_end=6256 + _globals['_UNDELETERULEREQUEST']._serialized_start=6258 + _globals['_UNDELETERULEREQUEST']._serialized_end=6345 + _globals['_UNDELETERULERESPONSE']._serialized_start=6347 + _globals['_UNDELETERULERESPONSE']._serialized_end=6369 + _globals['_BATCHUNDELETERULESREQUEST']._serialized_start=6371 + _globals['_BATCHUNDELETERULESREQUEST']._serialized_end=6468 + _globals['_BATCHUNDELETERULESRESPONSE']._serialized_start=6470 + _globals['_BATCHUNDELETERULESRESPONSE']._serialized_end=6498 + _globals['_VIEWHUMANFRIENDLYRULESREQUEST']._serialized_start=6500 + _globals['_VIEWHUMANFRIENDLYRULESREQUEST']._serialized_end=6567 + _globals['_VIEWHUMANFRIENDLYRULESRESPONSE']._serialized_start=6569 + _globals['_VIEWHUMANFRIENDLYRULESRESPONSE']._serialized_end=6641 + _globals['_UPDATEHUMANFRIENDLYRULESREQUEST']._serialized_start=6644 + _globals['_UPDATEHUMANFRIENDLYRULESREQUEST']._serialized_end=6795 + _globals['_UPDATEHUMANFRIENDLYRULESRESPONSE']._serialized_start=6798 + _globals['_UPDATEHUMANFRIENDLYRULESRESPONSE']._serialized_end=6938 + _globals['_VIEWJSONRULESREQUEST']._serialized_start=6940 + _globals['_VIEWJSONRULESREQUEST']._serialized_end=6994 + _globals['_VIEWJSONRULESRESPONSE']._serialized_start=6996 + _globals['_VIEWJSONRULESRESPONSE']._serialized_end=7055 + _globals['_JSONRULESREQUEST']._serialized_start=7058 + _globals['_JSONRULESREQUEST']._serialized_end=7190 + _globals['_JSONRULESRESPONSE']._serialized_start=7193 + _globals['_JSONRULESRESPONSE']._serialized_end=7514 + _globals['_VALIDATEJSONRULESREQUEST']._serialized_start=7516 + _globals['_VALIDATEJSONRULESREQUEST']._serialized_end=7606 + _globals['_VALIDATEJSONRULESRESPONSE']._serialized_start=7608 + _globals['_VALIDATEJSONRULESRESPONSE']._serialized_end=7702 + _globals['_UPDATEJSONRULESREQUEST']._serialized_start=7704 + _globals['_UPDATEJSONRULESREQUEST']._serialized_end=7792 + _globals['_UPDATEJSONRULESRESPONSE']._serialized_start=7794 + _globals['_UPDATEJSONRULESRESPONSE']._serialized_end=7886 + _globals['_LISTRULESREQUEST']._serialized_start=7889 + _globals['_LISTRULESREQUEST']._serialized_end=8038 + _globals['_LISTRULESRESPONSE']._serialized_start=8040 + _globals['_LISTRULESRESPONSE']._serialized_end=8147 + _globals['_LISTRULEVERSIONSREQUEST']._serialized_start=8150 + _globals['_LISTRULEVERSIONSREQUEST']._serialized_end=8299 + _globals['_RULEVERSION']._serialized_start=8302 + _globals['_RULEVERSION']._serialized_end=8712 + _globals['_LISTRULEVERSIONSRESPONSE']._serialized_start=8715 + _globals['_LISTRULEVERSIONSRESPONSE']._serialized_end=8851 + _globals['_GETRULEVERSIONREQUEST']._serialized_start=8853 + _globals['_GETRULEVERSIONREQUEST']._serialized_end=8921 + _globals['_GETRULEVERSIONRESPONSE']._serialized_start=8923 + _globals['_GETRULEVERSIONRESPONSE']._serialized_end=8993 + _globals['_BATCHGETRULEVERSIONSREQUEST']._serialized_start=8995 + _globals['_BATCHGETRULEVERSIONSREQUEST']._serialized_end=9071 + _globals['_BATCHGETRULEVERSIONSRESPONSE']._serialized_start=9073 + _globals['_BATCHGETRULEVERSIONSRESPONSE']._serialized_end=9151 + _globals['_RULECONDITIONEXPRESSION']._serialized_start=9154 + _globals['_RULECONDITIONEXPRESSION']._serialized_end=9398 + _globals['_SINGLECHANNELCOMPARISONEXPRESSION']._serialized_start=9401 + _globals['_SINGLECHANNELCOMPARISONEXPRESSION']._serialized_end=9732 + _globals['_LASTVALUETHRESHOLD']._serialized_start=9734 + _globals['_LASTVALUETHRESHOLD']._serialized_end=9754 + _globals['_CALCULATEDCHANNELCONFIG']._serialized_start=9757 + _globals['_CALCULATEDCHANNELCONFIG']._serialized_end=10136 + _globals['_CALCULATEDCHANNELCONFIG_CHANNELREFERENCESENTRY']._serialized_start=10035 + _globals['_CALCULATEDCHANNELCONFIG_CHANNELREFERENCESENTRY']._serialized_end=10136 + _globals['_CHANNELREFERENCE']._serialized_start=10138 + _globals['_CHANNELREFERENCE']._serialized_end=10216 + _globals['_RULEACTIONCONFIGURATION']._serialized_start=10219 + _globals['_RULEACTIONCONFIGURATION']._serialized_end=10427 + _globals['_NOTIFICATIONACTIONCONFIGURATION']._serialized_start=10429 + _globals['_NOTIFICATIONACTIONCONFIGURATION']._serialized_end=10513 + _globals['_ANNOTATIONACTIONCONFIGURATION']._serialized_start=10516 + _globals['_ANNOTATIONACTIONCONFIGURATION']._serialized_end=10792 + _globals['_EVALUATERULESREQUEST']._serialized_start=10795 + _globals['_EVALUATERULESREQUEST']._serialized_end=11065 + _globals['_EVALUATEDANNOTATIONOPTIONS']._serialized_start=11067 + _globals['_EVALUATEDANNOTATIONOPTIONS']._serialized_end=11120 + _globals['_TIMERANGEQUERY']._serialized_start=11123 + _globals['_TIMERANGEQUERY']._serialized_end=11253 + _globals['_EVALUATERULESRESPONSE']._serialized_start=11256 + _globals['_EVALUATERULESRESPONSE']._serialized_end=11509 + _globals['_DRYRUNANNOTATION']._serialized_start=11512 + _globals['_DRYRUNANNOTATION']._serialized_end=11759 + _globals['_RULESERVICE']._serialized_start=12126 + _globals['_RULESERVICE']._serialized_end=16302 # @@protoc_insertion_point(module_scope) diff --git a/python/lib/sift/rules/v1/rules_pb2.pyi b/python/lib/sift/rules/v1/rules_pb2.pyi index 4eebde0fc..0a577483c 100644 --- a/python/lib/sift/rules/v1/rules_pb2.pyi +++ b/python/lib/sift/rules/v1/rules_pb2.pyi @@ -20,6 +20,7 @@ import google.protobuf.timestamp_pb2 import sift.annotations.v1.annotations_pb2 import sift.common.type.v1.resource_identifier_pb2 import sift.common.type.v1.user_defined_functions_pb2 +import sift.metadata.v1.metadata_pb2 import sys import typing @@ -112,6 +113,7 @@ class Rule(google.protobuf.message.Message): CONTEXTUAL_CHANNELS_FIELD_NUMBER: builtins.int DELETED_DATE_FIELD_NUMBER: builtins.int IS_EXTERNAL_FIELD_NUMBER: builtins.int + METADATA_FIELD_NUMBER: builtins.int rule_id: builtins.str asset_id: builtins.str name: builtins.str @@ -137,6 +139,8 @@ class Rule(google.protobuf.message.Message): def contextual_channels(self) -> global___ContextualChannels: ... @property def deleted_date(self) -> google.protobuf.timestamp_pb2.Timestamp: ... + @property + def metadata(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[sift.metadata.v1.metadata_pb2.MetadataValue]: ... def __init__( self, *, @@ -157,9 +161,10 @@ class Rule(google.protobuf.message.Message): contextual_channels: global___ContextualChannels | None = ..., deleted_date: google.protobuf.timestamp_pb2.Timestamp | None = ..., is_external: builtins.bool = ..., + metadata: collections.abc.Iterable[sift.metadata.v1.metadata_pb2.MetadataValue] | None = ..., ) -> None: ... def HasField(self, field_name: typing.Literal["asset_configuration", b"asset_configuration", "contextual_channels", b"contextual_channels", "created_date", b"created_date", "deleted_date", b"deleted_date", "modified_date", b"modified_date", "rule_version", b"rule_version"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["asset_configuration", b"asset_configuration", "asset_id", b"asset_id", "client_key", b"client_key", "conditions", b"conditions", "contextual_channels", b"contextual_channels", "created_by_user_id", b"created_by_user_id", "created_date", b"created_date", "deleted_date", b"deleted_date", "description", b"description", "is_enabled", b"is_enabled", "is_external", b"is_external", "modified_by_user_id", b"modified_by_user_id", "modified_date", b"modified_date", "name", b"name", "organization_id", b"organization_id", "rule_id", b"rule_id", "rule_version", b"rule_version"]) -> None: ... + def ClearField(self, field_name: typing.Literal["asset_configuration", b"asset_configuration", "asset_id", b"asset_id", "client_key", b"client_key", "conditions", b"conditions", "contextual_channels", b"contextual_channels", "created_by_user_id", b"created_by_user_id", "created_date", b"created_date", "deleted_date", b"deleted_date", "description", b"description", "is_enabled", b"is_enabled", "is_external", b"is_external", "metadata", b"metadata", "modified_by_user_id", b"modified_by_user_id", "modified_date", b"modified_date", "name", b"name", "organization_id", b"organization_id", "rule_id", b"rule_id", "rule_version", b"rule_version"]) -> None: ... global___Rule = Rule @@ -523,12 +528,14 @@ class UpdateRuleRequest(google.protobuf.message.Message): ASSET_CONFIGURATION_FIELD_NUMBER: builtins.int CONTEXTUAL_CHANNELS_FIELD_NUMBER: builtins.int IS_EXTERNAL_FIELD_NUMBER: builtins.int + METADATA_FIELD_NUMBER: builtins.int rule_id: builtins.str name: builtins.str description: builtins.str asset_id: builtins.str """Deprecated - use asset_configuration instead.""" is_enabled: builtins.bool + """Deprecated - use DeleteRule instead.""" organization_id: builtins.str version_notes: builtins.str client_key: builtins.str @@ -540,6 +547,8 @@ class UpdateRuleRequest(google.protobuf.message.Message): def asset_configuration(self) -> global___RuleAssetConfiguration: ... @property def contextual_channels(self) -> global___ContextualChannels: ... + @property + def metadata(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[sift.metadata.v1.metadata_pb2.MetadataValue]: ... def __init__( self, *, @@ -555,9 +564,10 @@ class UpdateRuleRequest(google.protobuf.message.Message): asset_configuration: global___RuleAssetConfiguration | None = ..., contextual_channels: global___ContextualChannels | None = ..., is_external: builtins.bool = ..., + metadata: collections.abc.Iterable[sift.metadata.v1.metadata_pb2.MetadataValue] | None = ..., ) -> None: ... def HasField(self, field_name: typing.Literal["_client_key", b"_client_key", "_rule_id", b"_rule_id", "asset_configuration", b"asset_configuration", "client_key", b"client_key", "contextual_channels", b"contextual_channels", "rule_id", b"rule_id"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["_client_key", b"_client_key", "_rule_id", b"_rule_id", "asset_configuration", b"asset_configuration", "asset_id", b"asset_id", "client_key", b"client_key", "conditions", b"conditions", "contextual_channels", b"contextual_channels", "description", b"description", "is_enabled", b"is_enabled", "is_external", b"is_external", "name", b"name", "organization_id", b"organization_id", "rule_id", b"rule_id", "version_notes", b"version_notes"]) -> None: ... + def ClearField(self, field_name: typing.Literal["_client_key", b"_client_key", "_rule_id", b"_rule_id", "asset_configuration", b"asset_configuration", "asset_id", b"asset_id", "client_key", b"client_key", "conditions", b"conditions", "contextual_channels", b"contextual_channels", "description", b"description", "is_enabled", b"is_enabled", "is_external", b"is_external", "metadata", b"metadata", "name", b"name", "organization_id", b"organization_id", "rule_id", b"rule_id", "version_notes", b"version_notes"]) -> None: ... @typing.overload def WhichOneof(self, oneof_group: typing.Literal["_client_key", b"_client_key"]) -> typing.Literal["client_key"] | None: ... @typing.overload @@ -1128,14 +1138,14 @@ class ListRulesRequest(google.protobuf.message.Message): """ filter: builtins.str """A [Common Expression Language (CEL)](https://github.com/google/cel-spec) filter string. - Available fields to filter by are `rule_id`, `client_key`, `name`, and `description`. + Available fields to filter by are `rule_id`, `client_key`, `name`, `description`, `asset_id`, `tag_id`, and `deleted_date`. For further information about how to use CELs, please refer to [this guide](https://github.com/google/cel-spec/blob/master/doc/langdef.md#standard-definitions). Optional. """ order_by: builtins.str """How to order the retrieved Rules. Formatted as a comma-separated string i.e. "FIELD_NAME[ desc],...". Available fields to order_by are `created_date` and `modified_date`. - If left empty, items are ordered by `created_date` in ascending order (oldest-first). + If left empty, items are ordered by `created_date` in descending order (newest-first). """ def __init__( self, @@ -1334,25 +1344,19 @@ class RuleConditionExpression(google.protobuf.message.Message): SINGLE_CHANNEL_COMPARISON_FIELD_NUMBER: builtins.int CALCULATED_CHANNEL_FIELD_NUMBER: builtins.int - PYTHON_CODE_FIELD_NUMBER: builtins.int @property def single_channel_comparison(self) -> global___SingleChannelComparisonExpression: ... @property def calculated_channel(self) -> global___CalculatedChannelConfig: ... - @property - def python_code(self) -> global___PythonCode: - """Experimental - not currently enabled""" - def __init__( self, *, single_channel_comparison: global___SingleChannelComparisonExpression | None = ..., calculated_channel: global___CalculatedChannelConfig | None = ..., - python_code: global___PythonCode | None = ..., ) -> None: ... - def HasField(self, field_name: typing.Literal["calculated_channel", b"calculated_channel", "expression", b"expression", "python_code", b"python_code", "single_channel_comparison", b"single_channel_comparison"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["calculated_channel", b"calculated_channel", "expression", b"expression", "python_code", b"python_code", "single_channel_comparison", b"single_channel_comparison"]) -> None: ... - def WhichOneof(self, oneof_group: typing.Literal["expression", b"expression"]) -> typing.Literal["single_channel_comparison", "calculated_channel", "python_code"] | None: ... + def HasField(self, field_name: typing.Literal["calculated_channel", b"calculated_channel", "expression", b"expression", "single_channel_comparison", b"single_channel_comparison"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["calculated_channel", b"calculated_channel", "expression", b"expression", "single_channel_comparison", b"single_channel_comparison"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["expression", b"expression"]) -> typing.Literal["single_channel_comparison", "calculated_channel"] | None: ... global___RuleConditionExpression = RuleConditionExpression @@ -1464,46 +1468,6 @@ class ChannelReference(google.protobuf.message.Message): global___ChannelReference = ChannelReference -@typing.final -class PythonChannelReference(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - REFERENCE_FIELD_NUMBER: builtins.int - NAME_FIELD_NUMBER: builtins.int - reference: builtins.str - name: builtins.str - def __init__( - self, - *, - reference: builtins.str = ..., - name: builtins.str = ..., - ) -> None: ... - def ClearField(self, field_name: typing.Literal["name", b"name", "reference", b"reference"]) -> None: ... - -global___PythonChannelReference = PythonChannelReference - -@typing.final -class PythonCode(google.protobuf.message.Message): - DESCRIPTOR: google.protobuf.descriptor.Descriptor - - CHANNEL_REFERENCES_FIELD_NUMBER: builtins.int - CODE_FIELD_NUMBER: builtins.int - DEPENDENCIES_FIELD_NUMBER: builtins.int - code: builtins.str - dependencies: builtins.str - @property - def channel_references(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___PythonChannelReference]: ... - def __init__( - self, - *, - channel_references: collections.abc.Iterable[global___PythonChannelReference] | None = ..., - code: builtins.str = ..., - dependencies: builtins.str = ..., - ) -> None: ... - def ClearField(self, field_name: typing.Literal["channel_references", b"channel_references", "code", b"code", "dependencies", b"dependencies"]) -> None: ... - -global___PythonCode = PythonCode - @typing.final class RuleActionConfiguration(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -1549,19 +1513,23 @@ class AnnotationActionConfiguration(google.protobuf.message.Message): TAG_IDS_FIELD_NUMBER: builtins.int ANNOTATION_TYPE_FIELD_NUMBER: builtins.int ASSIGNED_TO_USER_ID_FIELD_NUMBER: builtins.int + METADATA_FIELD_NUMBER: builtins.int annotation_type: sift.annotations.v1.annotations_pb2.AnnotationType.ValueType assigned_to_user_id: builtins.str @property def tag_ids(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ... + @property + def metadata(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[sift.metadata.v1.metadata_pb2.MetadataValue]: ... def __init__( self, *, tag_ids: collections.abc.Iterable[builtins.str] | None = ..., annotation_type: sift.annotations.v1.annotations_pb2.AnnotationType.ValueType = ..., assigned_to_user_id: builtins.str | None = ..., + metadata: collections.abc.Iterable[sift.metadata.v1.metadata_pb2.MetadataValue] | None = ..., ) -> None: ... def HasField(self, field_name: typing.Literal["_assigned_to_user_id", b"_assigned_to_user_id", "assigned_to_user_id", b"assigned_to_user_id"]) -> builtins.bool: ... - def ClearField(self, field_name: typing.Literal["_assigned_to_user_id", b"_assigned_to_user_id", "annotation_type", b"annotation_type", "assigned_to_user_id", b"assigned_to_user_id", "tag_ids", b"tag_ids"]) -> None: ... + def ClearField(self, field_name: typing.Literal["_assigned_to_user_id", b"_assigned_to_user_id", "annotation_type", b"annotation_type", "assigned_to_user_id", b"assigned_to_user_id", "metadata", b"metadata", "tag_ids", b"tag_ids"]) -> None: ... def WhichOneof(self, oneof_group: typing.Literal["_assigned_to_user_id", b"_assigned_to_user_id"]) -> typing.Literal["assigned_to_user_id"] | None: ... global___AnnotationActionConfiguration = AnnotationActionConfiguration diff --git a/python/lib/sift_client/_internal/low_level_wrappers/__init__.py b/python/lib/sift_client/_internal/low_level_wrappers/__init__.py index 6bdef7f17..2105116b0 100644 --- a/python/lib/sift_client/_internal/low_level_wrappers/__init__.py +++ b/python/lib/sift_client/_internal/low_level_wrappers/__init__.py @@ -5,6 +5,7 @@ from sift_client._internal.low_level_wrappers.channels import ChannelsLowLevelClient from sift_client._internal.low_level_wrappers.ingestion import IngestionLowLevelClient from sift_client._internal.low_level_wrappers.ping import PingLowLevelClient +from sift_client._internal.low_level_wrappers.reports import ReportsLowLevelClient from sift_client._internal.low_level_wrappers.rules import RulesLowLevelClient from sift_client._internal.low_level_wrappers.runs import RunsLowLevelClient @@ -14,6 +15,7 @@ "ChannelsLowLevelClient", "IngestionLowLevelClient", "PingLowLevelClient", + "ReportsLowLevelClient", "RulesLowLevelClient", "RunsLowLevelClient", ] diff --git a/python/lib/sift_client/_internal/low_level_wrappers/reports.py b/python/lib/sift_client/_internal/low_level_wrappers/reports.py new file mode 100644 index 000000000..63ed10207 --- /dev/null +++ b/python/lib/sift_client/_internal/low_level_wrappers/reports.py @@ -0,0 +1,268 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING, Any, cast + +from sift.reports.v1.reports_pb2 import ( + CancelReportRequest, + CreateReportFromReportTemplateRequest, + CreateReportFromRulesRequest, + CreateReportRequest, + CreateReportRequestClientKeys, + CreateReportRequestRuleIds, + CreateReportResponse, + GetReportRequest, + GetReportResponse, + ListReportsRequest, + ListReportsResponse, + RerunReportRequest, + RerunReportResponse, +) +from sift.reports.v1.reports_pb2_grpc import ReportServiceStub + +from sift_client._internal.low_level_wrappers.base import LowLevelClientBase +from sift_client.sift_types.report import Report +from sift_client.transport import WithGrpcClient + +if TYPE_CHECKING: + from sift_client.transport.grpc_transport import GrpcClient + +# Configure logging +logger = logging.getLogger(__name__) + + +class ReportsLowLevelClient(LowLevelClientBase, WithGrpcClient): + """Low-level client for the ReportsAPI. + + This class provides a thin wrapper around the autogenerated bindings for the ReportsAPI. + """ + + def __init__(self, grpc_client: GrpcClient): + """Initialize the ReportsLowLevelClient. + + Args: + grpc_client: The gRPC client to use for making API calls. + """ + super().__init__(grpc_client) + + async def get_report(self, report_id: str) -> Report: + """Get a report by report_id. + + Args: + report_id: The report ID to get. + + Returns: + The Report. + + Raises: + ValueError: If report_id is not provided. + """ + if not report_id: + raise ValueError("report_id must be provided") + + request = GetReportRequest(report_id=report_id) + response = await self._grpc_client.get_stub(ReportServiceStub).GetReport(request) + grpc_report = cast("GetReportResponse", response).report + return Report._from_proto(grpc_report) + + async def list_reports( + self, + *, + page_size: int | None = None, + page_token: str | None = None, + query_filter: str | None = None, + organization_id: str | None = None, + order_by: str | None = None, + ) -> tuple[list[Report], str]: + """List reports with optional filtering and pagination. + + Args: + page_size: The maximum number of reports to return. + page_token: A page token for pagination. + query_filter: A CEL filter string. + organization_id: The organization ID to filter by. + order_by: How to order the retrieved reports. + + Returns: + A tuple of (reports, next_page_token). + """ + request_kwargs: dict[str, Any] = {} + if page_size is not None: + request_kwargs["page_size"] = page_size + if page_token is not None: + request_kwargs["page_token"] = page_token + if query_filter is not None: + request_kwargs["filter"] = query_filter + if organization_id is not None: + request_kwargs["organization_id"] = organization_id + if order_by is not None: + request_kwargs["order_by"] = order_by + + request = ListReportsRequest(**request_kwargs) + response = await self._grpc_client.get_stub(ReportServiceStub).ListReports(request) + response = cast("ListReportsResponse", response) + + reports = [Report._from_proto(report) for report in response.reports] + return reports, response.next_page_token + + async def list_all_reports( + self, + *, + query_filter: str | None = None, + organization_id: str | None = None, + order_by: str | None = None, + max_results: int | None = None, + ) -> list[Report]: + """List all reports with optional filtering. + + Args: + query_filter: A CEL filter string. + organization_id: The organization ID to filter by. + order_by: How to order the retrieved reports. + max_results: Maximum number of results to return. + + Returns: + A list of all matching reports. + """ + return await self._handle_pagination( + self.list_reports, + kwargs={ + "query_filter": query_filter, + "organization_id": organization_id, + }, + order_by=order_by, + max_results=max_results, + ) + + async def create_report_from_template( + self, + *, + report_template_id: str, + run_id: str, + organization_id: str, + name: str | None = None, + ) -> Report: + """Create a new report from a report template. + + Args: + report_template_id: The ID of the report template to use. + run_id: The run ID to associate with the report. + organization_id: The organization ID. + name: Optional name for the report. + + Returns: + The created Report. + """ + template_request = CreateReportFromReportTemplateRequest( + report_template_id=report_template_id + ) + + request_kwargs: dict[str, Any] = { + "report_from_report_template_request": template_request, + "organization_id": organization_id, + "run_id": run_id, + } + + if name is not None: + request_kwargs["name"] = name + + request = CreateReportRequest(**request_kwargs) + response = await self._grpc_client.get_stub(ReportServiceStub).CreateReport(request) + grpc_report = cast("CreateReportResponse", response).report + return Report._from_proto(grpc_report) + + async def create_report_from_rules( + self, + *, + name: str, + description: str | None = None, + tag_names: list[str] | None = None, + rule_ids: list[str] | None = None, + rule_client_keys: list[str] | None = None, + run_id: str, + organization_id: str, + ) -> Report: + """Create a new report from rules. + + Args: + name: The name of the report. + description: Optional description of the report. + tag_names: List of tag names to associate with the report. + rule_ids: List of rule IDs to include in the report. + rule_client_keys: List of rule client keys to include in the report. + run_id: The run ID to associate with the report. + organization_id: The organization ID. + + Returns: + The created Report. + + Raises: + ValueError: If neither rule_ids nor rule_client_keys are provided. + """ + if not rule_ids and not rule_client_keys: + raise ValueError("Either rule_ids or rule_client_keys must be provided") + + rules_request_kwargs: dict[str, Any] = { + "name": name, + } + + if description is not None: + rules_request_kwargs["description"] = description + + if tag_names is not None: + rules_request_kwargs["tag_names"] = tag_names + + if rule_ids is not None: + rules_request_kwargs["rule_ids"] = CreateReportRequestRuleIds(rule_ids=rule_ids) + elif rule_client_keys is not None: + rules_request_kwargs["rule_client_keys"] = CreateReportRequestClientKeys( + rule_client_keys=rule_client_keys + ) + + rules_request = CreateReportFromRulesRequest(**rules_request_kwargs) + + request_kwargs: dict[str, Any] = { + "report_from_rules_request": rules_request, + "organization_id": organization_id, + "run_id": run_id, + } + + request = CreateReportRequest(**request_kwargs) + response = await self._grpc_client.get_stub(ReportServiceStub).CreateReport(request) + grpc_report = cast("CreateReportResponse", response).report + return Report._from_proto(grpc_report) + + async def rerun_report(self, report_id: str) -> tuple[str, str]: + """Rerun a report. + + Args: + report_id: The ID of the report to rerun. + + Returns: + A tuple of (job_id, new_report_id). + + Raises: + ValueError: If report_id is not provided. + """ + if not report_id: + raise ValueError("report_id must be provided") + + request = RerunReportRequest(report_id=report_id) + response = await self._grpc_client.get_stub(ReportServiceStub).RerunReport(request) + response = cast("RerunReportResponse", response) + return response.job_id, response.report_id + + async def cancel_report(self, report_id: str) -> None: + """Cancel a report. + + Args: + report_id: The ID of the report to cancel. + + Raises: + ValueError: If report_id is not provided. + """ + if not report_id: + raise ValueError("report_id must be provided") + + request = CancelReportRequest(report_id=report_id) + await self._grpc_client.get_stub(ReportServiceStub).CancelReport(request) diff --git a/python/lib/sift_client/_internal/low_level_wrappers/rules.py b/python/lib/sift_client/_internal/low_level_wrappers/rules.py index 676b5fa71..435ff4bb5 100644 --- a/python/lib/sift_client/_internal/low_level_wrappers/rules.py +++ b/python/lib/sift_client/_internal/low_level_wrappers/rules.py @@ -3,6 +3,13 @@ import logging from typing import TYPE_CHECKING, Any, cast +from sift.common.type.v1.resource_identifier_pb2 import ResourceIdentifier +from sift.rule_evaluation.v1.rule_evaluation_pb2 import ( + EvaluateRulesRequest, + EvaluateRulesResponse, + RunTimeRange, +) +from sift.rule_evaluation.v1.rule_evaluation_pb2_grpc import RuleEvaluationServiceStub from sift.rules.v1.rules_pb2 import ( BatchDeleteRulesRequest, BatchGetRulesRequest, @@ -31,15 +38,20 @@ from sift.rules.v1.rules_pb2_grpc import RuleServiceStub from sift_client._internal.low_level_wrappers.base import LowLevelClientBase +from sift_client._internal.low_level_wrappers.reports import ReportsLowLevelClient from sift_client.sift_types.rule import ( Rule, RuleAction, RuleUpdate, ) from sift_client.transport import GrpcClient, WithGrpcClient +from sift_client.util.util import count_non_none if TYPE_CHECKING: + from datetime import datetime + from sift_client.sift_types.channel import ChannelReference + from sift_client.sift_types.report import Report # Configure logging logger = logging.getLogger(__name__) @@ -445,3 +457,76 @@ async def list_all_rules( order_by=order_by, max_results=max_results, ) + + async def evaluate_rules( + self, + *, + run_id: str | None = None, + assets: list[str] | None = None, + all_applicable_rules: bool | None = None, + run_start_time: datetime | None = None, + run_end_time: datetime | None = None, + rule_ids: list[str] | None = None, + rule_version_ids: list[str] | None = None, + report_template_id: str | None = None, + tags: list[str] | None = None, + ) -> Report | None: + """Evaluate a rule. + + Args: + run_id: The run ID to evaluate. + assets: The assets to evaluate. + run_start_time: The start time of the run. + run_end_time: The end time of the run. + all_applicable_rules: Whether to evaluate all rules applicable to the selected run, assets, or time range. + rule_ids: The rule IDs to evaluate. + rule_version_ids: The rule version IDs to evaluate. + report_template_id: The report template ID to evaluate. + tags: Optional tags to add to generated annotations. + + Returns: + The result of the rule execution. + """ + if count_non_none(run_id, assets, run_start_time, run_end_time) > 1: + raise ValueError( + "Pick only one run_id, assets, or (run_start_time and run_end_time) to select what to evaluate against." + ) + + all_applicable_rules = ( + None if not all_applicable_rules else True + ) # Cast to None if False so we don't count it against other filters if they aren't opting in. + if count_non_none(rule_ids, rule_version_ids, report_template_id, all_applicable_rules) > 1: + raise ValueError( + "Pick only one rule_ids, rule_version_ids, report_template_id, or all_applicable_rules to further filter which rules to evaluate." + ) + + kwargs: dict[str, Any] = {} + if run_start_time and run_end_time: + kwargs["run_time_range"] = RunTimeRange( + run=run_id, start_time=run_start_time, end_time=run_end_time + ) + if run_id: + kwargs["run"] = ResourceIdentifier(id=run_id) + if assets: + kwargs["assets"] = assets + if all_applicable_rules: + kwargs["all_applicable_rules"] = all_applicable_rules + if rule_ids: + kwargs["rules"] = rule_ids + if rule_version_ids: + kwargs["rule_versions"] = rule_version_ids + if report_template_id: + kwargs["report_template"] = report_template_id + if tags: + kwargs["tags"] = tags + + request = EvaluateRulesRequest(**kwargs) + response = await self._grpc_client.get_stub(RuleEvaluationServiceStub).EvaluateRules( + request + ) + response = cast("EvaluateRulesResponse", response) + report_id = response.report_id + if report_id: + report = await ReportsLowLevelClient(self._grpc_client).get_report(report_id=report_id) + return report + return None diff --git a/python/lib/sift_client/_internal/low_level_wrappers/tags.py b/python/lib/sift_client/_internal/low_level_wrappers/tags.py new file mode 100644 index 000000000..4ae12a4e4 --- /dev/null +++ b/python/lib/sift_client/_internal/low_level_wrappers/tags.py @@ -0,0 +1,117 @@ +from __future__ import annotations + +import logging +from typing import TYPE_CHECKING, Any, cast + +from sift.tags.v2.tags_pb2 import ( + CreateTagRequest, + CreateTagResponse, + ListTagsRequest, + ListTagsResponse, +) +from sift.tags.v2.tags_pb2_grpc import TagServiceStub + +from sift_client._internal.low_level_wrappers.base import LowLevelClientBase +from sift_client.sift_types.tag import Tag +from sift_client.transport import WithGrpcClient + +if TYPE_CHECKING: + from sift_client.transport.grpc_transport import GrpcClient + +# Configure logging +logger = logging.getLogger(__name__) + + +class TagsLowLevelClient(LowLevelClientBase, WithGrpcClient): + """Low-level client for the TagsAPI. + + This class provides a thin wrapper around the autogenerated bindings for the TagsAPI. + """ + + def __init__(self, grpc_client: GrpcClient): + """Initialize the TagsLowLevelClient. + + Args: + grpc_client: The gRPC client to use for making API calls. + """ + super().__init__(grpc_client) + + async def create_tag(self, name: str) -> Tag: + """Create a new tag. + + Args: + name: The name of the tag. + + Returns: + The created Tag. + + Raises: + ValueError: If name is not provided. + """ + if not name: + raise ValueError("name must be provided") + + request = CreateTagRequest(name=name) + response = await self._grpc_client.get_stub(TagServiceStub).CreateTag(request) + grpc_tag = cast("CreateTagResponse", response).tag + return Tag._from_proto(grpc_tag) + + async def list_tags( + self, + *, + page_size: int | None = None, + page_token: str | None = None, + query_filter: str | None = None, + order_by: str | None = None, + ) -> tuple[list[Tag], str]: + """List tags with optional filtering and pagination. + + Args: + page_size: The maximum number of tags to return. + page_token: A page token for pagination. + query_filter: A CEL filter string. + order_by: How to order the retrieved tags. + + Returns: + A tuple of (tags, next_page_token). + """ + request_kwargs: dict[str, Any] = {} + if page_size is not None: + request_kwargs["page_size"] = page_size + if page_token is not None: + request_kwargs["page_token"] = page_token + if query_filter is not None: + request_kwargs["filter"] = query_filter + if order_by is not None: + request_kwargs["order_by"] = order_by + + request = ListTagsRequest(**request_kwargs) + response = await self._grpc_client.get_stub(TagServiceStub).ListTags(request) + response = cast("ListTagsResponse", response) + + tags = [Tag._from_proto(tag) for tag in response.tags] + return tags, response.next_page_token + + async def list_all_tags( + self, + *, + query_filter: str | None = None, + order_by: str | None = None, + max_results: int | None = None, + ) -> list[Tag]: + """List all tags with optional filtering. + + Args: + query_filter: A CEL filter string. + order_by: How to order the retrieved tags. + max_results: Maximum number of results to return. + + Returns: + A list of all matching tags. + """ + return await self._handle_pagination( + self.list_tags, + kwargs={"query_filter": query_filter}, + order_by=order_by, + max_results=max_results, + ) diff --git a/python/lib/sift_client/_tests/integrated/reports.py b/python/lib/sift_client/_tests/integrated/reports.py new file mode 100644 index 000000000..8f94bed3f --- /dev/null +++ b/python/lib/sift_client/_tests/integrated/reports.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""This test demonstrates the usage of the Runs API. + +It creates a new run, updates it, and associates assets with it. +It also lists runs, filters them, and deletes the run. + +It uses the SiftClient to interact with the API. +""" + +import asyncio +import os +from datetime import datetime + +from zoneinfo import ZoneInfo + +from sift_client import SiftClient + + +async def main(): + """Main function demonstrating the Runs API usage.""" + # Initialize the client + # You can set these environment variables or pass them directly + grpc_url = os.getenv("SIFT_GRPC_URI", "localhost:50051") + rest_url = os.getenv("SIFT_REST_URI", "localhost:8080") + api_key = os.getenv("SIFT_API_KEY", "") + grpc_url = "https://gov.grpc-api.siftstack.com" + rest_url = "https://gov.api.siftstack.com" + # api_key = os.getenv("SIFT_GOV_API_KEY", "") + api_key = "wRmqGJUrVMWujDtRUquf23I7X0D4MbEVLB0CRsIk" + client = SiftClient( + api_key=api_key, + grpc_url=grpc_url, + rest_url=rest_url, + ) + + runs = client.runs.list_( + created_date_start=datetime(2025, 9, 10, 9, 50, tzinfo=ZoneInfo("America/Los_Angeles")), + created_date_end=datetime(2025, 9, 10, 12, 50, tzinfo=ZoneInfo("America/Los_Angeles")), + limit=100, + ) + + rules = [] + failed_runs = [] + for run in runs: + print("run.name: ", run.name) + print(" client_key: ", run.client_key) + try: + report = client.rules.evaluate( + run_id=run.id_, + all_applicable_rules=True, + ) + except Exception as e: + failed_runs.append(run.id_) + print(f"Failed to evaluate rules for run {run.id_}: {e}") + + print("Number of successful runs: ", len(runs) - len(failed_runs)) + print("Number of failed runs: ", len(failed_runs)) + + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/lib/sift_client/client.py b/python/lib/sift_client/client.py index 427e4def5..d122a896a 100644 --- a/python/lib/sift_client/client.py +++ b/python/lib/sift_client/client.py @@ -11,10 +11,14 @@ IngestionAPIAsync, PingAPI, PingAPIAsync, + ReportsAPI, + ReportsAPIAsync, RulesAPI, RulesAPIAsync, RunsAPI, RunsAPIAsync, + TagsAPI, + TagsAPIAsync, ) from sift_client.transport import ( GrpcClient, @@ -80,12 +84,18 @@ class SiftClient( ingestion: IngestionAPIAsync """Instance of the Ingestion API for making synchronous requests.""" + reports: ReportsAPI + """Instance of the Reports API for making synchronous requests.""" + rules: RulesAPI """Instance of the Rules API for making synchronous requests.""" runs: RunsAPI """Instance of the Runs API for making synchronous requests.""" + tags: TagsAPI + """Instance of the Tags API for making synchronous requests.""" + async_: AsyncAPIs """Accessor for the asynchronous APIs. All asynchronous APIs are available as attributes on this accessor.""" @@ -130,7 +140,8 @@ def __init__( self.ingestion = IngestionAPIAsync(self) self.rules = RulesAPI(self) self.runs = RunsAPI(self) - + self.reports = ReportsAPI(self) + self.tags = TagsAPI(self) # Accessor for the asynchronous APIs self.async_ = AsyncAPIs( ping=PingAPIAsync(self), @@ -140,6 +151,8 @@ def __init__( ingestion=IngestionAPIAsync(self), rules=RulesAPIAsync(self), runs=RunsAPIAsync(self), + reports=ReportsAPIAsync(self), + tags=TagsAPIAsync(self), ) @property diff --git a/python/lib/sift_client/resources/__init__.py b/python/lib/sift_client/resources/__init__.py index 5997acb02..5810fe7cc 100644 --- a/python/lib/sift_client/resources/__init__.py +++ b/python/lib/sift_client/resources/__init__.py @@ -3,15 +3,21 @@ from sift_client.resources.channels import ChannelsAPIAsync from sift_client.resources.ingestion import IngestionAPIAsync from sift_client.resources.ping import PingAPIAsync +from sift_client.resources.reports import ReportsAPIAsync from sift_client.resources.rules import RulesAPIAsync from sift_client.resources.runs import RunsAPIAsync +from sift_client.resources.tags import TagsAPIAsync + +# ruff: noqa TagsAPIAsync needs to be imported before sync_stubs to avoid circular import from sift_client.resources.sync_stubs import ( AssetsAPI, CalculatedChannelsAPI, ChannelsAPI, PingAPI, + ReportsAPI, RulesAPI, RunsAPI, + TagsAPI, ) __all__ = [ @@ -24,8 +30,12 @@ "IngestionAPIAsync", "PingAPI", "PingAPIAsync", + "ReportsAPI", + "ReportsAPIAsync", "RulesAPI", "RulesAPIAsync", "RunsAPI", "RunsAPIAsync", + "TagsAPI", + "TagsAPIAsync", ] diff --git a/python/lib/sift_client/resources/reports.py b/python/lib/sift_client/resources/reports.py new file mode 100644 index 000000000..e3b3263e1 --- /dev/null +++ b/python/lib/sift_client/resources/reports.py @@ -0,0 +1,234 @@ +from __future__ import annotations + +import re +from typing import TYPE_CHECKING + +from sift_client._internal.low_level_wrappers.reports import ReportsLowLevelClient +from sift_client.resources._base import ResourceBase +from sift_client.sift_types.report import Report +from sift_client.util.cel_utils import contains, equals, match + +if TYPE_CHECKING: + from sift_client.client import SiftClient + + +class ReportsAPIAsync(ResourceBase): + """High-level API for interacting with reports.""" + + def __init__(self, sift_client: SiftClient): + """Initialize the ReportsAPI. + + Args: + sift_client: The Sift client to use. + """ + super().__init__(sift_client) + self._low_level_client = ReportsLowLevelClient(grpc_client=self.client.grpc_client) + + async def get( + self, + *, + report_id: str, + ) -> Report: + """Get a Report. + + Args: + report_id: The ID of the report. + + Returns: + The Report. + """ + report = await self._low_level_client.get_report(report_id=report_id) + return self._apply_client_to_instance(report) + + async def list_( + self, + *, + name: str | None = None, + name_contains: str | None = None, + name_regex: str | re.Pattern | None = None, + description: str | None = None, + description_contains: str | None = None, + run_id: str | None = None, + organization_id: str | None = None, + created_by_user_id: str | None = None, + modified_by_user_id: str | None = None, + report_template_id: str | None = None, + tag_name: str | None = None, + order_by: str | None = None, + limit: int | None = None, + ) -> list[Report]: + """List reports with optional filtering. + + Args: + name: Exact name of the report. + name_contains: Partial name of the report. + name_regex: Regular expression string to filter reports by name. + description: Exact description of the report. + description_contains: Partial description of the report. + run_id: Run ID to filter by. + organization_id: Organization ID to filter by. + created_by_user_id: User ID who created the report. + modified_by_user_id: User ID who modified the report. + report_template_id: Report template ID to filter by. + tag_name: Tag name to filter by. + order_by: How to order the retrieved reports. + limit: How many reports to retrieve. If None, retrieves all matches. + + Returns: + A list of Reports that matches the filter. + """ + # Build CEL filter + filter_parts = [] + + if name: + filter_parts.append(equals("name", name)) + elif name_contains: + filter_parts.append(contains("name", name_contains)) + elif name_regex: + if isinstance(name_regex, re.Pattern): + name_regex = name_regex.pattern + filter_parts.append(match("name", name_regex)) # type: ignore + + if description: + filter_parts.append(equals("description", description)) + elif description_contains: + filter_parts.append(contains("description", description_contains)) + + if run_id: + filter_parts.append(equals("run_id", run_id)) + + if organization_id: + filter_parts.append(equals("organization_id", organization_id)) + + if created_by_user_id: + filter_parts.append(equals("created_by_user_id", created_by_user_id)) + + if modified_by_user_id: + filter_parts.append(equals("modified_by_user_id", modified_by_user_id)) + + if report_template_id: + filter_parts.append(equals("report_template_id", report_template_id)) + + if tag_name: + filter_parts.append(contains("tags", tag_name)) + + query_filter = " && ".join(filter_parts) if filter_parts else None + + reports = await self._low_level_client.list_all_reports( + query_filter=query_filter, + organization_id=organization_id, + order_by=order_by, + max_results=limit, + ) + return self._apply_client_to_instances(reports) + + async def find(self, **kwargs) -> Report | None: + """Find a single report matching the given query. Takes the same arguments as `list`. If more than one report is found, + raises an error. + + Args: + **kwargs: Keyword arguments to pass to `list`. + + Returns: + The Report found or None. + """ + reports = await self.list_(**kwargs) + if len(reports) > 1: + raise ValueError("Multiple reports found for query") + elif len(reports) == 1: + return reports[0] + return None + + async def create_from_template( + self, + report_template_id: str, + run_id: str, + organization_id: str, + name: str | None = None, + ) -> Report: + """Create a new report from a report template. + + Args: + report_template_id: The ID of the report template to use. + run_id: The run ID to associate with the report. + organization_id: The organization ID. + name: Optional name for the report. + + Returns: + The created Report. + """ + created_report = await self._low_level_client.create_report_from_template( + report_template_id=report_template_id, + run_id=run_id, + organization_id=organization_id, + name=name, + ) + return self._apply_client_to_instance(created_report) + + async def create_from_rules( + self, + name: str, + run_id: str, + organization_id: str, + description: str | None = None, + tag_names: list[str] | None = None, + rule_ids: list[str] | None = None, + rule_client_keys: list[str] | None = None, + ) -> Report: + """Create a new report from rules. + + Args: + name: The name of the report. + run_id: The run ID to associate with the report. + organization_id: The organization ID. + description: Optional description of the report. + tag_names: List of tag names to associate with the report. + rule_ids: List of rule IDs to include in the report. + rule_client_keys: List of rule client keys to include in the report. + + Returns: + The created Report. + """ + created_report = await self._low_level_client.create_report_from_rules( + name=name, + description=description, + tag_names=tag_names, + rule_ids=rule_ids, + rule_client_keys=rule_client_keys, + run_id=run_id, + organization_id=organization_id, + ) + return self._apply_client_to_instance(created_report) + + async def rerun( + self, + *, + report: str | Report, + ) -> tuple[str, str]: + """Rerun a report. + + Args: + report: The Report or report ID to rerun. + + Returns: + A tuple of (job_id, new_report_id). + """ + report_id = report.id_ if isinstance(report, Report) else report + if not isinstance(report_id, str): + raise TypeError(f"report_id must be a string not {type(report_id)}") + return await self._low_level_client.rerun_report(report_id=report_id) + + async def cancel( + self, + *, + report: str | Report, + ) -> None: + """Cancel a report. + + Args: + report: The Report or report ID to cancel. + """ + report_id = report.id_ if isinstance(report, Report) else report + if not isinstance(report_id, str): + raise TypeError(f"report_id must be a string not {type(report_id)}") + await self._low_level_client.cancel_report(report_id=report_id) diff --git a/python/lib/sift_client/resources/rules.py b/python/lib/sift_client/resources/rules.py index a101a3ae5..ff7b6ef0e 100644 --- a/python/lib/sift_client/resources/rules.py +++ b/python/lib/sift_client/resources/rules.py @@ -9,9 +9,11 @@ if TYPE_CHECKING: import re + from datetime import datetime from sift_client.client import SiftClient from sift_client.sift_types.channel import ChannelReference + from sift_client.sift_types.report import Report class RulesAPIAsync(ResourceBase): @@ -57,6 +59,9 @@ async def list_( name: str | None = None, name_contains: str | None = None, name_regex: str | re.Pattern | None = None, + asset_ids: list[str] | None = None, + asset_tags_ids: list[str] | None = None, + client_key: str | None = None, order_by: str | None = None, limit: int | None = None, include_deleted: bool = False, @@ -67,6 +72,9 @@ async def list_( name: Exact name of the rule. name_contains: Partial name of the rule. name_regex: Regular expression string to filter rules by name. + asset_ids: List of asset IDs to filter rules by. + asset_tags_ids: List of asset tags IDs to filter rules by. + client_key: The client key of the rules. order_by: How to order the retrieved rules. limit: How many rules to retrieve. If None, retrieves all matches. include_deleted: Include deleted rules. @@ -84,9 +92,16 @@ async def list_( filters.append(cel.contains("name", name_contains)) if name_regex: filters.append(cel.match("name", name_regex)) + if asset_ids: + filters.append(cel.in_("asset_id", asset_ids)) + if asset_tags_ids: + filters.append(cel.in_("tag_id", asset_tags_ids)) + if client_key: + filters.append(cel.equals("client_key", client_key)) + # We mostly want to OR these filters except for the deleted_date filter + filter_str = " || ".join(filters) if filters else "" if not include_deleted: - filters.append(cel.equals_null("deleted_date")) - filter_str = " && ".join(filters) if filters else "" + filter_str = f"({filter_str}) && {cel.equals_null('deleted_date')}" rules = await self._low_level_client.list_all_rules( filter_query=filter_str, order_by=order_by, @@ -260,3 +275,56 @@ async def batch_get( rule_ids=rule_ids, client_keys=client_keys ) return self._apply_client_to_instances(rules) + + async def evaluate( + self, + *, + run_id: str | None = None, + assets: list[str] | None = None, + all_applicable_rules: bool | None = None, + run_start_time: datetime | None = None, + run_end_time: datetime | None = None, + rule_ids: list[str] | None = None, + rule_version_ids: list[str] | None = None, + report_template_id: str | None = None, + tags: list[str] | None = None, + ) -> Report | None: + """Evaluate a rule. + + Pick one of the following grouping of rules to evaluate against: + - run_id + - assets + - run_start_time and run_end_time + And one of the following filters to select which rules to evaluate: + - rule_ids + - rule_version_ids + - report_template_id + - all_applicable_rules + + Args: + run_id: The run ID to evaluate. + assets: The assets to evaluate. + all_applicable_rules: Whether to evaluate all rules applicable to the selected run, assets, or time range. + run_start_time: The start time of the run. + run_end_time: The end time of the run. + rule_ids: The rule IDs to evaluate. + rule_version_ids: The rule version IDs to evaluate. + report_template_id: The report template ID to evaluate. + tags: Optional tags to add to generated annotations. + + Returns: + The result of the rule evaluation. + """ + report = await self._low_level_client.evaluate_rules( + run_id=run_id, + assets=assets, + all_applicable_rules=all_applicable_rules, + run_start_time=run_start_time, + run_end_time=run_end_time, + rule_ids=rule_ids, + rule_version_ids=rule_version_ids, + report_template_id=report_template_id, + tags=tags, + ) + if report: + return self._apply_client_to_instance(report) diff --git a/python/lib/sift_client/resources/runs.py b/python/lib/sift_client/resources/runs.py index abb324f89..9c7543e43 100644 --- a/python/lib/sift_client/resources/runs.py +++ b/python/lib/sift_client/resources/runs.py @@ -6,7 +6,16 @@ from sift_client._internal.low_level_wrappers.runs import RunsLowLevelClient from sift_client.resources._base import ResourceBase from sift_client.sift_types.run import Run, RunUpdate -from sift_client.util.cel_utils import contains, equals, equals_null, match, not_ +from sift_client.util.cel_utils import ( + contains, + equals, + equals_null, + greater_than, + in_, + less_than, + match, + not_, +) if TYPE_CHECKING: from datetime import datetime @@ -55,6 +64,7 @@ async def list_( name: str | None = None, name_contains: str | None = None, name_regex: str | re.Pattern | None = None, + run_ids: list[str] | None = None, description: str | None = None, description_contains: str | None = None, duration_seconds: int | None = None, @@ -63,7 +73,16 @@ async def list_( asset_name: str | None = None, created_by_user_id: str | None = None, is_stopped: bool | None = None, + created_date_start: datetime | None = None, + created_date_end: datetime | None = None, + modified_date_start: datetime | None = None, + modified_date_end: datetime | None = None, + start_time_start: datetime | None = None, + start_time_end: datetime | None = None, + stop_time_start: datetime | None = None, + stop_time_end: datetime | None = None, include_archived: bool = False, + organization_id: str | None = None, order_by: str | None = None, limit: int | None = None, ) -> list[Run]: @@ -73,6 +92,7 @@ async def list_( name: Exact name of the run. name_contains: Partial name of the run. name_regex: Regular expression string to filter runs by name. + run_ids: List of run IDs to filter by. description: Exact description of the run. description_contains: Partial description of the run. duration_seconds: Duration of the run in seconds. @@ -81,7 +101,16 @@ async def list_( asset_name: Asset name to filter by. created_by_user_id: User ID who created the run. is_stopped: Whether the run is stopped. + created_date_start: Start date for created_date filter. + created_date_end: End date for created_date filter. + modified_date_start: Start date for modified_date filter. + modified_date_end: End date for modified_date filter. + start_time_start: Start date for start_time filter. + start_time_end: End date for start_time filter. + stop_time_start: Start date for stop_time filter. + stop_time_end: End date for stop_time filter. include_archived: Whether to include archived runs. + organization_id: Organization ID to filter by. order_by: How to order the retrieved runs. limit: How many runs to retrieve. If None, retrieves all matches. @@ -100,6 +129,9 @@ async def list_( name_regex = name_regex.pattern filter_parts.append(match("name", name_regex)) # type: ignore + if run_ids: + filter_parts.append(in_("run_id", run_ids)) + if description: filter_parts.append(equals("description", description)) elif description_contains: @@ -126,6 +158,33 @@ async def list_( if not include_archived: filter_parts.append(equals("archived_date", None)) + if created_date_start: + filter_parts.append(greater_than("created_date", created_date_start)) + + if created_date_end: + filter_parts.append(less_than("created_date", created_date_end)) + + if modified_date_start: + filter_parts.append(greater_than("modified_date", modified_date_start)) + + if modified_date_end: + filter_parts.append(less_than("modified_date", modified_date_end)) + + if start_time_start: + filter_parts.append(greater_than("start_time", start_time_start)) + + if start_time_end: + filter_parts.append(less_than("start_time", start_time_end)) + + if stop_time_start: + filter_parts.append(greater_than("stop_time", stop_time_start)) + + if stop_time_end: + filter_parts.append(less_than("stop_time", stop_time_end)) + + if organization_id: + filter_parts.append(equals("organization_id", organization_id)) + query_filter = " && ".join(filter_parts) if filter_parts else None runs = await self._low_level_client.list_all_runs( diff --git a/python/lib/sift_client/resources/sync_stubs/__init__.py b/python/lib/sift_client/resources/sync_stubs/__init__.py index 7246389a4..dca41435b 100644 --- a/python/lib/sift_client/resources/sync_stubs/__init__.py +++ b/python/lib/sift_client/resources/sync_stubs/__init__.py @@ -8,8 +8,10 @@ CalculatedChannelsAPIAsync, ChannelsAPIAsync, PingAPIAsync, + ReportsAPIAsync, RulesAPIAsync, RunsAPIAsync, + TagsAPIAsync, ) PingAPI = generate_sync_api(PingAPIAsync, "PingAPI") @@ -18,5 +20,7 @@ ChannelsAPI = generate_sync_api(ChannelsAPIAsync, "ChannelsAPI") RulesAPI = generate_sync_api(RulesAPIAsync, "RulesAPI") RunsAPI = generate_sync_api(RunsAPIAsync, "RunsAPI") +ReportsAPI = generate_sync_api(ReportsAPIAsync, "ReportsAPI") +TagsAPI = generate_sync_api(TagsAPIAsync, "TagsAPI") -__all__ = ["AssetsAPI", "CalculatedChannelsAPI", "PingAPI", "RunsAPI"] +__all__ = ["AssetsAPI", "CalculatedChannelsAPI", "PingAPI", "ReportsAPI", "RunsAPI", "TagsAPI"] diff --git a/python/lib/sift_client/resources/sync_stubs/__init__.pyi b/python/lib/sift_client/resources/sync_stubs/__init__.pyi index 0c52d3b15..be4a93745 100644 --- a/python/lib/sift_client/resources/sync_stubs/__init__.pyi +++ b/python/lib/sift_client/resources/sync_stubs/__init__.pyi @@ -13,20 +13,21 @@ from sift_client.client import SiftClient from sift_client.sift_types.asset import Asset, AssetUpdate from sift_client.sift_types.calculated_channel import CalculatedChannel, CalculatedChannelUpdate from sift_client.sift_types.channel import Channel, ChannelReference +from sift_client.sift_types.report import Report from sift_client.sift_types.rule import Rule, RuleAction, RuleUpdate from sift_client.sift_types.run import Run, RunUpdate +from sift_client.sift_types.tag import Tag, TagUpdate class AssetsAPI: """Sync counterpart to `AssetsAPIAsync`. High-level API for interacting with assets. - This class provides a Pythonic, notebook-friendly interface for interacting with the AssetsAPI. - It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. - - All methods in this class use the Asset class from the low-level wrapper, which is a user-friendly - representation of an asset using standard Python data structures and types. + This class provides a Pythonic, notebook-friendly interface for interacting with the AssetsAPI. + It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. + All methods in this class use the Asset class from the low-level wrapper, which is a user-friendly + representation of an asset using standard Python data structures and types. """ def __init__(self, sift_client: SiftClient): @@ -139,12 +140,11 @@ class CalculatedChannelsAPI: High-level API for interacting with calculated channels. - This class provides a Pythonic, notebook-friendly interface for interacting with the CalculatedChannelsAPI. - It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. - - All methods in this class use the CalculatedChannel class from the low-level wrapper, which is a user-friendly - representation of a calculated channel using standard Python data structures and types. + This class provides a Pythonic, notebook-friendly interface for interacting with the CalculatedChannelsAPI. + It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. + All methods in this class use the CalculatedChannel class from the low-level wrapper, which is a user-friendly + representation of a calculated channel using standard Python data structures and types. """ def __init__(self, sift_client: SiftClient): @@ -351,12 +351,11 @@ class ChannelsAPI: High-level API for interacting with channels. - This class provides a Pythonic, notebook-friendly interface for interacting with the ChannelsAPI. - It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. - - All methods in this class use the Channel class from the low-level wrapper, which is a user-friendly - representation of a channel using standard Python data structures and types. + This class provides a Pythonic, notebook-friendly interface for interacting with the ChannelsAPI. + It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. + All methods in this class use the Channel class from the low-level wrapper, which is a user-friendly + representation of a channel using standard Python data structures and types. """ def __init__(self, sift_client: SiftClient): @@ -491,17 +490,154 @@ class PingAPI: """ ... +class ReportsAPI: + """Sync counterpart to `ReportsAPIAsync`. + + High-level API for interacting with reports. + """ + + def __init__(self, sift_client: SiftClient): + """Initialize the ReportsAPI. + + Args: + sift_client: The Sift client to use. + """ + ... + + def _run(self, coro): ... + def cancel(self, *, report: str | Report) -> None: + """Cancel a report. + + Args: + report: The Report or report ID to cancel. + """ + ... + + def create_from_rules( + self, + name: str, + run_id: str, + organization_id: str, + description: str | None = None, + tag_names: list[str] | None = None, + rule_ids: list[str] | None = None, + rule_client_keys: list[str] | None = None, + ) -> Report: + """Create a new report from rules. + + Args: + name: The name of the report. + run_id: The run ID to associate with the report. + organization_id: The organization ID. + description: Optional description of the report. + tag_names: List of tag names to associate with the report. + rule_ids: List of rule IDs to include in the report. + rule_client_keys: List of rule client keys to include in the report. + + Returns: + The created Report. + """ + ... + + def create_from_template( + self, report_template_id: str, run_id: str, organization_id: str, name: str | None = None + ) -> Report: + """Create a new report from a report template. + + Args: + report_template_id: The ID of the report template to use. + run_id: The run ID to associate with the report. + organization_id: The organization ID. + name: Optional name for the report. + + Returns: + The created Report. + """ + ... + + def find(self, **kwargs) -> Report | None: + """Find a single report matching the given query. Takes the same arguments as `list`. If more than one report is found, + raises an error. + + Args: + **kwargs: Keyword arguments to pass to `list`. + + Returns: + The Report found or None. + """ + ... + + def get(self, *, report_id: str) -> Report: + """Get a Report. + + Args: + report_id: The ID of the report. + + Returns: + The Report. + """ + ... + + def list_( + self, + *, + name: str | None = None, + name_contains: str | None = None, + name_regex: str | re.Pattern | None = None, + description: str | None = None, + description_contains: str | None = None, + run_id: str | None = None, + organization_id: str | None = None, + created_by_user_id: str | None = None, + modified_by_user_id: str | None = None, + report_template_id: str | None = None, + tag_name: str | None = None, + order_by: str | None = None, + limit: int | None = None, + ) -> list[Report]: + """List reports with optional filtering. + + Args: + name: Exact name of the report. + name_contains: Partial name of the report. + name_regex: Regular expression string to filter reports by name. + description: Exact description of the report. + description_contains: Partial description of the report. + run_id: Run ID to filter by. + organization_id: Organization ID to filter by. + created_by_user_id: User ID who created the report. + modified_by_user_id: User ID who modified the report. + report_template_id: Report template ID to filter by. + tag_name: Tag name to filter by. + order_by: How to order the retrieved reports. + limit: How many reports to retrieve. If None, retrieves all matches. + + Returns: + A list of Reports that matches the filter. + """ + ... + + def rerun(self, *, report: str | Report) -> tuple[str, str]: + """Rerun a report. + + Args: + report: The Report or report ID to rerun. + + Returns: + A tuple of (job_id, new_report_id). + """ + ... + class RulesAPI: """Sync counterpart to `RulesAPIAsync`. High-level API for interacting with rules. - This class provides a Pythonic, notebook-friendly interface for interacting with the RulesAPI. - It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. - - All methods in this class use the Rule class from the low-level wrapper, which is a user-friendly - representation of a rule using standard Python data structures and types. + This class provides a Pythonic, notebook-friendly interface for interacting with the RulesAPI. + It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. + All methods in this class use the Rule class from the low-level wrapper, which is a user-friendly + representation of a rule using standard Python data structures and types. """ def __init__(self, sift_client: SiftClient): @@ -572,6 +708,47 @@ class RulesAPI: """Create a new rule.""" ... + def evaluate( + self, + *, + run_id: str | None = None, + assets: list[str] | None = None, + all_applicable_rules: bool | None = None, + run_start_time: datetime | None = None, + run_end_time: datetime | None = None, + rule_ids: list[str] | None = None, + rule_version_ids: list[str] | None = None, + report_template_id: str | None = None, + tags: list[str] | None = None, + ) -> Report | None: + """Evaluate a rule. + + Pick one of the following grouping of rules to evaluate against: + - run_id + - assets + - run_start_time and run_end_time + And one of the following filters to select which rules to evaluate: + - rule_ids + - rule_version_ids + - report_template_id + - all_applicable_rules + + Args: + run_id: The run ID to evaluate. + assets: The assets to evaluate. + all_applicable_rules: Whether to evaluate all rules applicable to the selected run, assets, or time range. + run_start_time: The start time of the run. + run_end_time: The end time of the run. + rule_ids: The rule IDs to evaluate. + rule_version_ids: The rule version IDs to evaluate. + report_template_id: The report template ID to evaluate. + tags: Optional tags to add to generated annotations. + + Returns: + The result of the rule evaluation. + """ + ... + def find(self, **kwargs) -> Rule | None: """Find a single rule matching the given query. Takes the same arguments as `list`. If more than one rule is found, raises an error. @@ -602,6 +779,9 @@ class RulesAPI: name: str | None = None, name_contains: str | None = None, name_regex: str | re.Pattern | None = None, + asset_ids: list[str] | None = None, + asset_tags_ids: list[str] | None = None, + client_key: str | None = None, order_by: str | None = None, limit: int | None = None, include_deleted: bool = False, @@ -612,6 +792,9 @@ class RulesAPI: name: Exact name of the rule. name_contains: Partial name of the rule. name_regex: Regular expression string to filter rules by name. + asset_ids: List of asset IDs to filter rules by. + asset_tags_ids: List of asset tags IDs to filter rules by. + client_key: The client key of the rules. order_by: How to order the retrieved rules. limit: How many rules to retrieve. If None, retrieves all matches. include_deleted: Include deleted rules. @@ -656,12 +839,11 @@ class RunsAPI: High-level API for interacting with runs. - This class provides a Pythonic, notebook-friendly interface for interacting with the RunsAPI. - It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. - - All methods in this class use the Run class from the low-level wrapper, which is a user-friendly - representation of a run using standard Python data structures and types. + This class provides a Pythonic, notebook-friendly interface for interacting with the RunsAPI. + It handles automatic handling of gRPC services, seamless type conversion, and clear error handling. + All methods in this class use the Run class from the low-level wrapper, which is a user-friendly + representation of a run using standard Python data structures and types. """ def __init__(self, sift_client: SiftClient): @@ -749,6 +931,7 @@ class RunsAPI: name: str | None = None, name_contains: str | None = None, name_regex: str | re.Pattern | None = None, + run_ids: list[str] | None = None, description: str | None = None, description_contains: str | None = None, duration_seconds: int | None = None, @@ -757,7 +940,16 @@ class RunsAPI: asset_name: str | None = None, created_by_user_id: str | None = None, is_stopped: bool | None = None, + created_date_start: datetime | None = None, + created_date_end: datetime | None = None, + modified_date_start: datetime | None = None, + modified_date_end: datetime | None = None, + start_time_start: datetime | None = None, + start_time_end: datetime | None = None, + stop_time_start: datetime | None = None, + stop_time_end: datetime | None = None, include_archived: bool = False, + organization_id: str | None = None, order_by: str | None = None, limit: int | None = None, ) -> list[Run]: @@ -767,6 +959,7 @@ class RunsAPI: name: Exact name of the run. name_contains: Partial name of the run. name_regex: Regular expression string to filter runs by name. + run_ids: List of run IDs to filter by. description: Exact description of the run. description_contains: Partial description of the run. duration_seconds: Duration of the run in seconds. @@ -775,7 +968,16 @@ class RunsAPI: asset_name: Asset name to filter by. created_by_user_id: User ID who created the run. is_stopped: Whether the run is stopped. + created_date_start: Start date for created_date filter. + created_date_end: End date for created_date filter. + modified_date_start: Start date for modified_date filter. + modified_date_end: End date for modified_date filter. + start_time_start: Start date for start_time filter. + start_time_end: End date for start_time filter. + stop_time_start: Start date for stop_time filter. + stop_time_end: End date for stop_time filter. include_archived: Whether to include archived runs. + organization_id: Organization ID to filter by. order_by: How to order the retrieved runs. limit: How many runs to retrieve. If None, retrieves all matches. @@ -811,3 +1013,86 @@ class RunsAPI: The updated Run. """ ... + +class TagsAPI: + """Sync counterpart to `TagsAPIAsync`. + + High-level API for interacting with tags. + """ + + def __init__(self, sift_client: SiftClient): + """Initialize the TagsAPI. + + Args: + sift_client: The Sift client to use. + """ + ... + + def _run(self, coro): ... + def create(self, name: str) -> Tag: + """Create a new tag. + + Args: + name: The name of the tag. + + Returns: + The created Tag. + """ + ... + + def find(self, **kwargs) -> Tag | None: + """Find a single tag matching the given query. Takes the same arguments as `list`. If more than one tag is found, + raises an error. + + Args: + **kwargs: Keyword arguments to pass to `list`. + + Returns: + The Tag found or None. + """ + ... + + def list_( + self, + *, + name: str | None = None, + name_contains: str | None = None, + name_regex: str | re.Pattern | None = None, + names: list[str] | None = None, + tag_ids: list[str] | None = None, + created_by_user_id: str | None = None, + order_by: str | None = None, + limit: int | None = None, + ) -> list[Tag]: + """List tags with optional filtering. + + Args: + name: Exact name of the tag. + name_contains: Partial name of the tag. + name_regex: Regular expression string to filter tags by name. + names: List of tag names to filter by. + tag_ids: List of tag IDs to filter by. + created_by_user_id: User ID who created the tag. + order_by: How to order the retrieved tags. + limit: How many tags to retrieve. If None, retrieves all matches. + + Returns: + A list of Tags that matches the filter. + """ + ... + + def update(self, tag: str | Tag, update: TagUpdate | dict) -> Tag: + """Update a Tag. + + Args: + tag: The Tag or tag ID to update. + update: Updates to apply to the Tag. + + Returns: + The updated Tag. + + Note: + The tags API doesn't have an update method in the proto, + so this would need to be implemented if the API supports it. + """ + ... diff --git a/python/lib/sift_client/resources/tags.py b/python/lib/sift_client/resources/tags.py new file mode 100644 index 000000000..f6b9fd0d0 --- /dev/null +++ b/python/lib/sift_client/resources/tags.py @@ -0,0 +1,128 @@ +from __future__ import annotations + +import re +from typing import TYPE_CHECKING + +from sift_client._internal.low_level_wrappers.tags import TagsLowLevelClient +from sift_client.resources._base import ResourceBase +from sift_client.util.cel_utils import contains, equals, in_, match + +if TYPE_CHECKING: + from sift_client.client import SiftClient + from sift_client.sift_types.tag import Tag, TagUpdate + + +class TagsAPIAsync(ResourceBase): + """High-level API for interacting with tags.""" + + def __init__(self, sift_client: SiftClient): + """Initialize the TagsAPI. + + Args: + sift_client: The Sift client to use. + """ + super().__init__(sift_client) + self._low_level_client = TagsLowLevelClient(grpc_client=self.client.grpc_client) + + async def list_( + self, + *, + name: str | None = None, + name_contains: str | None = None, + name_regex: str | re.Pattern | None = None, + names: list[str] | None = None, + tag_ids: list[str] | None = None, + created_by_user_id: str | None = None, + order_by: str | None = None, + limit: int | None = None, + ) -> list[Tag]: + """List tags with optional filtering. + + Args: + name: Exact name of the tag. + name_contains: Partial name of the tag. + name_regex: Regular expression string to filter tags by name. + names: List of tag names to filter by. + tag_ids: List of tag IDs to filter by. + created_by_user_id: User ID who created the tag. + order_by: How to order the retrieved tags. + limit: How many tags to retrieve. If None, retrieves all matches. + + Returns: + A list of Tags that matches the filter. + """ + # Build CEL filter + filter_parts = [] + + if name: + filter_parts.append(equals("name", name)) + elif name_contains: + filter_parts.append(contains("name", name_contains)) + elif name_regex: + if isinstance(name_regex, re.Pattern): + name_regex = name_regex.pattern + filter_parts.append(match("name", name_regex)) # type: ignore + + if names: + filter_parts.append(in_("name", names)) + if tag_ids: + filter_parts.append(in_("tag_id", tag_ids)) + + if created_by_user_id: + filter_parts.append(equals("created_by_user_id", created_by_user_id)) + + query_filter = " && ".join(filter_parts) if filter_parts else None + + tags = await self._low_level_client.list_all_tags( + query_filter=query_filter, + order_by=order_by, + max_results=limit, + ) + return self._apply_client_to_instances(tags) + + async def find(self, **kwargs) -> Tag | None: + """Find a single tag matching the given query. Takes the same arguments as `list`. If more than one tag is found, + raises an error. + + Args: + **kwargs: Keyword arguments to pass to `list`. + + Returns: + The Tag found or None. + """ + tags = await self.list_(**kwargs) + if len(tags) > 1: + raise ValueError("Multiple tags found for query") + elif len(tags) == 1: + return tags[0] + return None + + async def create(self, name: str) -> Tag: + """Create a new tag. + + Args: + name: The name of the tag. + + Returns: + The created Tag. + """ + created_tag = await self._low_level_client.create_tag(name=name) + return self._apply_client_to_instance(created_tag) + + async def update(self, tag: str | Tag, update: TagUpdate | dict) -> Tag: + """Update a Tag. + + Args: + tag: The Tag or tag ID to update. + update: Updates to apply to the Tag. + + Returns: + The updated Tag. + + Note: + The tags API doesn't have an update method in the proto, + so this would need to be implemented if the API supports it. + """ + # Note: The tags API doesn't have an update method in the proto, + # so this would need to be implemented if the API supports it + raise NotImplementedError("Tag updates are not supported by the current API") diff --git a/python/lib/sift_client/sift_types/__init__.py b/python/lib/sift_client/sift_types/__init__.py index 6a389fa51..88c235eaa 100644 --- a/python/lib/sift_client/sift_types/__init__.py +++ b/python/lib/sift_client/sift_types/__init__.py @@ -10,6 +10,7 @@ ChannelReference, ) from sift_client.sift_types.ingestion import IngestionConfig +from sift_client.sift_types.report import Report from sift_client.sift_types.rule import ( Rule, RuleAction, @@ -19,6 +20,7 @@ RuleVersion, ) from sift_client.sift_types.run import Run, RunUpdate +from sift_client.sift_types.tag import Tag, TagUpdate __all__ = [ "Asset", @@ -30,6 +32,7 @@ "ChannelDataType", "ChannelReference", "IngestionConfig", + "Report", "Rule", "RuleAction", "RuleActionType", @@ -38,4 +41,6 @@ "RuleVersion", "Run", "RunUpdate", + "Tag", + "TagUpdate", ] diff --git a/python/lib/sift_client/sift_types/report.py b/python/lib/sift_client/sift_types/report.py new file mode 100644 index 000000000..35c13e81f --- /dev/null +++ b/python/lib/sift_client/sift_types/report.py @@ -0,0 +1,129 @@ +from __future__ import annotations + +from datetime import datetime, timezone +from typing import TYPE_CHECKING + +from pydantic import ConfigDict +from sift.reports.v1.reports_pb2 import Report as ReportProto +from sift.reports.v1.reports_pb2 import ReportRuleSummary as ReportRuleSummaryProto +from sift.reports.v1.reports_pb2 import ReportTag as ReportTagProto + +from sift_client.sift_types._base import BaseType + +if TYPE_CHECKING: + from sift_client.client import SiftClient + + +class ReportRuleSummary(BaseType[ReportRuleSummaryProto, "ReportRuleSummary"]): + """ReportRuleSummary model representing a rule summary within a report.""" + + rule_id: str + rule_client_key: str | None = None + rule_version_id: str + rule_version_number: int + report_rule_version_id: str + num_open: int + num_failed: int + num_passed: int + status: int + created_date: datetime + modified_date: datetime + asset_id: str + deleted_date: datetime | None = None + + @classmethod + def _from_proto( + cls, proto: ReportRuleSummaryProto, sift_client: SiftClient | None = None + ) -> ReportRuleSummary: + return cls( + id_=proto.report_rule_version_id, + rule_id=proto.rule_id, + rule_client_key=proto.rule_client_key, + rule_version_id=proto.rule_version_id, + rule_version_number=proto.rule_version_number, + report_rule_version_id=proto.report_rule_version_id, + num_open=proto.num_open, + num_failed=proto.num_failed, + num_passed=proto.num_passed, + status=proto.status, + created_date=proto.created_date.ToDatetime(tzinfo=timezone.utc), + modified_date=proto.modified_date.ToDatetime(tzinfo=timezone.utc), + asset_id=proto.asset_id, + deleted_date=proto.deleted_date.ToDatetime(tzinfo=timezone.utc) + if proto.HasField("deleted_date") + else None, + _client=sift_client, + ) + + def _to_proto(self) -> ReportRuleSummaryProto: + """Convert to protobuf message.""" + return ReportRuleSummaryProto( + rule_id=self.rule_id, + rule_client_key=self.rule_client_key, + rule_version_id=self.rule_version_id, + rule_version_number=self.rule_version_number, + report_rule_version_id=self.report_rule_version_id, + num_open=self.num_open, + num_failed=self.num_failed, + num_passed=self.num_passed, + status=self.status, + created_date=self.created_date, + modified_date=self.modified_date, + asset_id=self.asset_id, + deleted_date=self.deleted_date, + ) + + +class Report(BaseType[ReportProto, "Report"]): + """Report model representing a data analysis report.""" + + model_config = ConfigDict(arbitrary_types_allowed=True) + + report_template_id: str + run_id: str + organization_id: str + name: str + description: str + created_by_user_id: str + modified_by_user_id: str + created_date: datetime + modified_date: datetime + summaries: list[ReportRuleSummary] + tags: list[str] + rerun_from_report_id: str + + @classmethod + def _from_proto(cls, proto: ReportProto, sift_client: SiftClient | None = None) -> Report: + return cls( + id_=proto.report_id, + report_template_id=proto.report_template_id, + run_id=proto.run_id, + organization_id=proto.organization_id, + name=proto.name, + description=proto.description, + created_by_user_id=proto.created_by_user_id, + modified_by_user_id=proto.modified_by_user_id, + created_date=proto.created_date.ToDatetime(tzinfo=timezone.utc), + modified_date=proto.modified_date.ToDatetime(tzinfo=timezone.utc), + summaries=[ + ReportRuleSummary._from_proto(summary, sift_client) for summary in proto.summaries + ], + tags=[tag.tag_name for tag in proto.tags], + rerun_from_report_id=proto.rerun_from_report_id, + _client=sift_client, + ) + + def _to_proto(self) -> ReportProto: + """Convert to protobuf message.""" + proto = ReportProto( + report_id=self.id_ or "", + run_id=self.run_id, + organization_id=self.organization_id, + name=self.name, + description=self.description, + report_template_id=self.report_template_id, + tags=[ReportTagProto(tag_name=tag) for tag in self.tags], + summaries=[summary._to_proto() for summary in self.summaries], + ) + + return proto diff --git a/python/lib/sift_client/sift_types/tag.py b/python/lib/sift_client/sift_types/tag.py new file mode 100644 index 000000000..1c46378d7 --- /dev/null +++ b/python/lib/sift_client/sift_types/tag.py @@ -0,0 +1,56 @@ +from __future__ import annotations + +from datetime import datetime, timezone +from typing import TYPE_CHECKING + +from pydantic import ConfigDict +from sift.tags.v2.tags_pb2 import Tag as TagProto + +from sift_client.sift_types._base import BaseType, ModelUpdate + +if TYPE_CHECKING: + from sift_client.client import SiftClient + + +class TagUpdate(ModelUpdate[TagProto]): + """Update model for Tag.""" + + name: str | None = None + + def _get_proto_class(self) -> type[TagProto]: + return TagProto + + def _add_resource_id_to_proto(self, proto_msg: TagProto): + if self._resource_id is None: + raise ValueError("Resource ID must be set before adding to proto") + proto_msg.tag_id = self._resource_id + + +class Tag(BaseType[TagProto, "Tag"]): + """Model of the Sift Tag.""" + + model_config = ConfigDict(arbitrary_types_allowed=True) + + name: str + created_date: datetime + created_by_user_id: str + + @classmethod + def _from_proto(cls, proto: TagProto, sift_client: SiftClient | None = None) -> Tag: + return cls( + id_=proto.tag_id, + name=proto.name, + created_date=proto.created_date.ToDatetime(tzinfo=timezone.utc), + created_by_user_id=proto.created_by_user_id, + _client=sift_client, + ) + + def _to_proto(self) -> TagProto: + """Convert to protobuf message.""" + proto = TagProto( + tag_id=self.id_ or "", + name=self.name, + created_by_user_id=self.created_by_user_id, + created_date=self.created_date, # type: ignore + ) + return proto diff --git a/python/lib/sift_client/util/cel_utils.py b/python/lib/sift_client/util/cel_utils.py index 219f6fe19..f2abba800 100644 --- a/python/lib/sift_client/util/cel_utils.py +++ b/python/lib/sift_client/util/cel_utils.py @@ -198,7 +198,7 @@ def greater_than(field: str, value: int | float | datetime) -> str: as_string = value.isoformat() else: as_string = str(value) - return f"{field} > {as_string}" + return f"{field} > timestamp('{as_string}')" def less_than(field: str, value: int | float | datetime) -> str: @@ -215,4 +215,4 @@ def less_than(field: str, value: int | float | datetime) -> str: as_string = value.isoformat() else: as_string = str(value) - return f"{field} < {as_string}" + return f"{field} < timestamp('{as_string}')" diff --git a/python/lib/sift_client/util/util.py b/python/lib/sift_client/util/util.py index 4202ee715..e631351e1 100644 --- a/python/lib/sift_client/util/util.py +++ b/python/lib/sift_client/util/util.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, NamedTuple +from typing import TYPE_CHECKING, Any, NamedTuple if TYPE_CHECKING: from sift_client.resources import ( @@ -9,8 +9,10 @@ ChannelsAPIAsync, IngestionAPIAsync, PingAPIAsync, + ReportsAPIAsync, RulesAPIAsync, RunsAPIAsync, + TagsAPIAsync, ) @@ -32,8 +34,19 @@ class AsyncAPIs(NamedTuple): ingestion: IngestionAPIAsync """Instance of the Ingestion API for making asynchronous requests.""" + reports: ReportsAPIAsync + """Instance of the Reports API for making asynchronous requests.""" + runs: RunsAPIAsync """Instance of the Runs API for making asynchronous requests.""" + tags: TagsAPIAsync + """Instance of the Tags API for making asynchronous requests.""" + rules: RulesAPIAsync """Instance of the Rules API for making asynchronous requests.""" + + +def count_non_none(*args: Any) -> int: + """Count the number of non-none arguments.""" + return sum(1 for arg in args if arg is not None)