noresponse 8.2.1 → 8.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/no_response/assessments.rb +293 -0
  3. data/lib/no_response/models/operations/aggregateassessments_response.rb +32 -0
  4. data/lib/no_response/models/operations/aggregateassessments_response.rbi +20 -0
  5. data/lib/no_response/models/operations.rb +1 -0
  6. data/lib/no_response/models/shared/aggregatebucket.rb +73 -0
  7. data/lib/no_response/models/shared/aggregatebucket.rbi +38 -0
  8. data/lib/no_response/models/shared/aggregatedimension.rb +26 -0
  9. data/lib/no_response/models/shared/aggregatedimension.rbi +9 -0
  10. data/lib/no_response/models/shared/aggregategroup.rb +179 -0
  11. data/lib/no_response/models/shared/aggregategroup.rbi +74 -0
  12. data/lib/no_response/models/shared/aggregatelateflip.rb +83 -0
  13. data/lib/no_response/models/shared/aggregatelateflip.rbi +32 -0
  14. data/lib/no_response/models/shared/aggregatescorecount.rb +63 -0
  15. data/lib/no_response/models/shared/aggregatescorecount.rbi +32 -0
  16. data/lib/no_response/models/shared/answerrevision.rb +16 -0
  17. data/lib/no_response/models/shared/answerrevision.rbi +9 -0
  18. data/lib/no_response/models/shared/assessmentaggregate.rb +121 -0
  19. data/lib/no_response/models/shared/assessmentaggregate.rbi +62 -0
  20. data/lib/no_response/models/shared/assessmentaggregate_metric.rb +20 -0
  21. data/lib/no_response/models/shared/assessmentaggregate_metric.rbi +9 -0
  22. data/lib/no_response/models/shared/assessmentaggregaterequest.rb +163 -0
  23. data/lib/no_response/models/shared/assessmentaggregaterequest.rbi +74 -0
  24. data/lib/no_response/models/shared/assessmentaggregaterequest_metric.rb +17 -0
  25. data/lib/no_response/models/shared/assessmentaggregaterequest_metric.rbi +9 -0
  26. data/lib/no_response/models/shared/assessmentsearchrequest.rb +17 -2
  27. data/lib/no_response/models/shared/assessmentsearchrequest.rbi +6 -0
  28. data/lib/no_response/models/shared/bucket.rb +20 -0
  29. data/lib/no_response/models/shared/bucket.rbi +9 -0
  30. data/lib/no_response/models/shared/decision.rb +5 -2
  31. data/lib/no_response/models/shared/delay.rb +23 -0
  32. data/lib/no_response/models/shared/delay.rbi +9 -0
  33. data/lib/no_response/models/shared/listmatch.rb +19 -0
  34. data/lib/no_response/models/shared/listmatch.rbi +9 -0
  35. data/lib/no_response/models/shared.rb +13 -0
  36. data/lib/no_response/sdkconfiguration.rb +2 -2
  37. metadata +29 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2de462c63f05c59d55e926053395a45fa2b45c6e10c45aa66f7ade4fc2e0447
4
- data.tar.gz: 77ff7a7d0b1b602b1a22b9644746277940a5793f938f27f83571fb7b5660f6c7
3
+ metadata.gz: 0f9e488e772432bf291e12c927572051286be92d2e7571b8a0d5897d413f1a9f
4
+ data.tar.gz: 41ce407e0b72b2cb45b757d87ec2f70353cb73f1d563f981865aadd239e3b933
5
5
  SHA512:
6
- metadata.gz: 3050ce89c6a1388e1f1419752a8cd954a608d02757b22f7d941561d996d3b49dec7a2a4409233e20fa96101ab43d59774b93d9ff9200f29ffaec725ccb29237e
7
- data.tar.gz: e8fc417da076ca6bbef8679ca7671392555ed6c89b31dc5ac7164fb2b46af80a46050796101b3b77da5a43ae4e7d1c6cae2e4693bfcb706ea13ce241ad328d9f
6
+ metadata.gz: 8244940ad0a13006308c976eecd9a5982144d36059373f18101d69c574fca874e1192c16af296d6e15473125fa668c8b02885795d1b4240c3c84e8e3e1cb8461
7
+ data.tar.gz: b130ae6e02b8d2db706cd843ff6b2ae9552c4d0ec869a3f96431cc76e75247a833adb0f64624f1c3a53ca9b10572cd7146cd4ec8b6f43d25b47eca77be747935
@@ -1537,6 +1537,299 @@ module NoResponse
1537
1537
  end
1538
1538
  end
1539
1539
 
1540
+ sig {
1541
+ params(
1542
+ request: Models::Shared::AssessmentAggregateRequest,
1543
+ retries: T.nilable(Utils::RetryConfig),
1544
+ timeout_ms: T.nilable(Integer),
1545
+ http_headers: T.nilable(T::Hash[T.any(String, Symbol), String])
1546
+ )
1547
+ .returns(Models::Operations::AggregateAssessmentsResponse)
1548
+ }
1549
+ def aggregate(request:, retries: nil, timeout_ms: nil, http_headers: nil)
1550
+ # aggregate - Count assessments by time, decision and reason
1551
+ # Count this environment's assessments created in [from,to) by hour, day or week, grouped by up to two of decision, flow, recommendation, band, reason, lane, country, asn and list_match. Each assessment counts once, by its first answer; late results do not count it again and appear in late_flips. Optional metrics add a score histogram per flow and late account decision changes. from and to start a bucket and cover at most 366 days (31 for hour buckets) inside the retention period. The filters are search's and describe the first answer: send them to search with revision first to list a cell's assessments. Counts hold no identifier, stay when an assessment or account is deleted, and report reasons by code and impact band. No Idempotency-Key.
1552
+ url, params = @sdk_configuration.get_server_details
1553
+ base_url = Utils.template_url(url, params)
1554
+ url = "#{base_url}/v1/assessments/aggregate"
1555
+ headers = {}
1556
+ headers = T.cast(headers, T::Hash[String, String])
1557
+ req_content_type, data, form = Utils.serialize_request_body(request, false, false, :request, :json)
1558
+ headers["content-type"] = req_content_type
1559
+ raise StandardError, "request body is required" if data.nil? && form.nil?
1560
+
1561
+ if form && !form.empty?
1562
+ body = Utils.encode_form(form)
1563
+ elsif Utils.match_content_type(req_content_type, "application/x-www-form-urlencoded")
1564
+ body = URI.encode_www_form(T.cast(data, T::Hash[Symbol, Object]))
1565
+ else
1566
+ body = data
1567
+ end
1568
+
1569
+ headers["Accept"] = "application/json"
1570
+ headers["user-agent"] = @sdk_configuration.user_agent
1571
+ retries ||= @sdk_configuration.retry_config
1572
+ retries ||= Utils::RetryConfig.new(
1573
+ backoff: Utils::BackoffStrategy.new(
1574
+ exponent: 2.0,
1575
+ initial_interval: 500,
1576
+ max_elapsed_time: 30_000,
1577
+ max_interval: 8000
1578
+ ),
1579
+ retry_connection_errors: true,
1580
+ strategy: "backoff"
1581
+ )
1582
+ retry_options = retries.to_faraday_retry_options(initial_time: Time.now)
1583
+ retry_options[:retry_statuses] = [408, 429, 500, 501, 502, 503, 504, 505]
1584
+
1585
+ security = @sdk_configuration.security_source&.call
1586
+
1587
+ timeout = (timeout_ms.to_f / 1000) unless timeout_ms.nil?
1588
+ timeout ||= @sdk_configuration.timeout
1589
+
1590
+ connection = @sdk_configuration.client.dup
1591
+ connection.use(Utils::RetryMiddleware, retry_options)
1592
+
1593
+ hook_ctx = SDKHooks::HookContext.new(
1594
+ config: @sdk_configuration,
1595
+ base_url: base_url,
1596
+ oauth2_scopes: nil,
1597
+ operation_id: "aggregateAssessments",
1598
+ security_source: @sdk_configuration.security_source
1599
+ )
1600
+
1601
+ error = T.let(nil, T.nilable(StandardError))
1602
+ http_response = T.let(nil, T.nilable(Faraday::Response))
1603
+
1604
+ begin
1605
+ http_response = T.must(connection).post(url) do |req|
1606
+ req.body = body
1607
+ req.headers.merge!(headers)
1608
+ req.options.timeout = timeout unless timeout.nil?
1609
+ Utils.configure_request_security(req, security)
1610
+ http_headers&.each do |key, value|
1611
+ req.headers[key.to_s] = value
1612
+ end
1613
+
1614
+ @sdk_configuration.hooks.before_request(
1615
+ hook_ctx: SDKHooks::BeforeRequestHookContext.new(
1616
+ hook_ctx: hook_ctx
1617
+ ),
1618
+ request: req
1619
+ )
1620
+ end
1621
+
1622
+ rescue StandardError => e
1623
+ error = e
1624
+ ensure
1625
+ if http_response.nil? || Utils.error_status?(http_response.status)
1626
+ http_response = @sdk_configuration.hooks.after_error(
1627
+ error: error,
1628
+ hook_ctx: SDKHooks::AfterErrorHookContext.new(
1629
+ hook_ctx: hook_ctx
1630
+ ),
1631
+ response: http_response
1632
+ )
1633
+ else
1634
+ http_response = @sdk_configuration.hooks.after_success(
1635
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
1636
+ hook_ctx: hook_ctx
1637
+ ),
1638
+ response: http_response
1639
+ )
1640
+ end
1641
+
1642
+ if http_response.nil?
1643
+ raise error if !error.nil?
1644
+ raise "no response"
1645
+ end
1646
+ end
1647
+
1648
+ content_type = http_response.headers.fetch("Content-Type", "application/octet-stream")
1649
+ if Utils.match_status_code(http_response.status, ["200"])
1650
+ if Utils.match_content_type(content_type, "application/json")
1651
+ @sdk_configuration.hooks.after_success(
1652
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
1653
+ hook_ctx: hook_ctx
1654
+ ),
1655
+ response: http_response
1656
+ )
1657
+ response_data = http_response.env.response_body
1658
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Shared::AssessmentAggregate)
1659
+ result = obj
1660
+ response = Models::Operations::AggregateAssessmentsResponse.new(
1661
+ result: result,
1662
+ headers: http_response.headers
1663
+ )
1664
+
1665
+ return response
1666
+ else
1667
+ raise(
1668
+ ::NoResponse::Models::Errors::APIStatusError.new(
1669
+ status_code: http_response.status,
1670
+ body: http_response.env.response_body,
1671
+ raw_response: http_response
1672
+ ),
1673
+ "Unknown content type received"
1674
+ )
1675
+ end
1676
+ elsif Utils.match_status_code(http_response.status, ["400"])
1677
+ if Utils.match_content_type(content_type, "application/problem+json")
1678
+ @sdk_configuration.hooks.after_success(
1679
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
1680
+ hook_ctx: hook_ctx
1681
+ ),
1682
+ response: http_response
1683
+ )
1684
+ response_data = http_response.env.response_body
1685
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::BadRequestError)
1686
+ raise obj
1687
+ else
1688
+ raise(
1689
+ ::NoResponse::Models::Errors::APIStatusError.new(
1690
+ status_code: http_response.status,
1691
+ body: http_response.env.response_body,
1692
+ raw_response: http_response
1693
+ ),
1694
+ "Unknown content type received"
1695
+ )
1696
+ end
1697
+ elsif Utils.match_status_code(http_response.status, ["401"])
1698
+ if Utils.match_content_type(content_type, "application/problem+json")
1699
+ @sdk_configuration.hooks.after_success(
1700
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
1701
+ hook_ctx: hook_ctx
1702
+ ),
1703
+ response: http_response
1704
+ )
1705
+ response_data = http_response.env.response_body
1706
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::AuthenticationError)
1707
+ raise obj
1708
+ else
1709
+ raise(
1710
+ ::NoResponse::Models::Errors::APIStatusError.new(
1711
+ status_code: http_response.status,
1712
+ body: http_response.env.response_body,
1713
+ raw_response: http_response
1714
+ ),
1715
+ "Unknown content type received"
1716
+ )
1717
+ end
1718
+ elsif Utils.match_status_code(http_response.status, ["403"])
1719
+ if Utils.match_content_type(content_type, "application/problem+json")
1720
+ @sdk_configuration.hooks.after_success(
1721
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
1722
+ hook_ctx: hook_ctx
1723
+ ),
1724
+ response: http_response
1725
+ )
1726
+ response_data = http_response.env.response_body
1727
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::PermissionDeniedError)
1728
+ raise obj
1729
+ else
1730
+ raise(
1731
+ ::NoResponse::Models::Errors::APIStatusError.new(
1732
+ status_code: http_response.status,
1733
+ body: http_response.env.response_body,
1734
+ raw_response: http_response
1735
+ ),
1736
+ "Unknown content type received"
1737
+ )
1738
+ end
1739
+ elsif Utils.match_status_code(http_response.status, ["404"])
1740
+ if Utils.match_content_type(content_type, "application/problem+json")
1741
+ @sdk_configuration.hooks.after_success(
1742
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
1743
+ hook_ctx: hook_ctx
1744
+ ),
1745
+ response: http_response
1746
+ )
1747
+ response_data = http_response.env.response_body
1748
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::NotFoundError)
1749
+ raise obj
1750
+ else
1751
+ raise(
1752
+ ::NoResponse::Models::Errors::APIStatusError.new(
1753
+ status_code: http_response.status,
1754
+ body: http_response.env.response_body,
1755
+ raw_response: http_response
1756
+ ),
1757
+ "Unknown content type received"
1758
+ )
1759
+ end
1760
+ elsif Utils.match_status_code(http_response.status, ["409"])
1761
+ if Utils.match_content_type(content_type, "application/problem+json")
1762
+ @sdk_configuration.hooks.after_success(
1763
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
1764
+ hook_ctx: hook_ctx
1765
+ ),
1766
+ response: http_response
1767
+ )
1768
+ response_data = http_response.env.response_body
1769
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::ConflictError)
1770
+ raise obj
1771
+ else
1772
+ raise(
1773
+ ::NoResponse::Models::Errors::APIStatusError.new(
1774
+ status_code: http_response.status,
1775
+ body: http_response.env.response_body,
1776
+ raw_response: http_response
1777
+ ),
1778
+ "Unknown content type received"
1779
+ )
1780
+ end
1781
+ elsif Utils.match_status_code(http_response.status, ["429"])
1782
+ if Utils.match_content_type(content_type, "application/problem+json")
1783
+ @sdk_configuration.hooks.after_success(
1784
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
1785
+ hook_ctx: hook_ctx
1786
+ ),
1787
+ response: http_response
1788
+ )
1789
+ response_data = http_response.env.response_body
1790
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::RateLimitError)
1791
+ raise obj
1792
+ else
1793
+ raise(
1794
+ ::NoResponse::Models::Errors::APIStatusError.new(
1795
+ status_code: http_response.status,
1796
+ body: http_response.env.response_body,
1797
+ raw_response: http_response
1798
+ ),
1799
+ "Unknown content type received"
1800
+ )
1801
+ end
1802
+ elsif Utils.match_status_code(http_response.status, ["4XX"])
1803
+ raise(
1804
+ ::NoResponse::Models::Errors::APIStatusError.new(
1805
+ status_code: http_response.status,
1806
+ body: http_response.env.response_body,
1807
+ raw_response: http_response
1808
+ ),
1809
+ "API error occurred"
1810
+ )
1811
+ elsif Utils.match_status_code(http_response.status, ["5XX"])
1812
+ raise(
1813
+ ::NoResponse::Models::Errors::APIStatusError.new(
1814
+ status_code: http_response.status,
1815
+ body: http_response.env.response_body,
1816
+ raw_response: http_response
1817
+ ),
1818
+ "API error occurred"
1819
+ )
1820
+ else
1821
+ raise(
1822
+ ::NoResponse::Models::Errors::APIStatusError.new(
1823
+ status_code: http_response.status,
1824
+ body: http_response.env.response_body,
1825
+ raw_response: http_response
1826
+ ),
1827
+ "Unknown status code received"
1828
+ )
1829
+
1830
+ end
1831
+ end
1832
+
1540
1833
  sig {
1541
1834
  params(
1542
1835
  request: Models::Shared::AssessmentSearchRequest,
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module NoResponse
5
+ module Models
6
+ module Operations
7
+
8
+ class AggregateAssessmentsResponse
9
+ extend T::Sig
10
+ include Crystalline::MetadataFields
11
+
12
+ field :headers, Crystalline::Hash.new(Symbol, Crystalline::Array.new(::String))
13
+
14
+ field :result, Models::Shared::AssessmentAggregate, {}
15
+
16
+ sig { params(headers: T::Hash[Symbol, T::Array[::String]], result: Models::Shared::AssessmentAggregate).void }
17
+ def initialize(headers:, result:)
18
+ @headers = headers
19
+ @result = result
20
+ end
21
+
22
+ sig { params(other: T.untyped).returns(T::Boolean) }
23
+ def ==(other)
24
+ return false unless other.is_a?(self.class)
25
+ return false unless @headers == other.headers
26
+ return false unless @result == other.result
27
+ true
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ class NoResponse::Models::Operations::AggregateAssessmentsResponse
5
+ extend ::Crystalline::MetadataFields::ClassMethods
6
+ end
7
+
8
+ class NoResponse::Models::Operations::AggregateAssessmentsResponse
9
+ def headers
10
+ end
11
+
12
+ def headers=(str_)
13
+ end
14
+
15
+ def result
16
+ end
17
+
18
+ def result=(str_)
19
+ end
20
+ end
@@ -4,6 +4,7 @@
4
4
  module NoResponse
5
5
  module Models
6
6
  module Operations
7
+ autoload :AggregateAssessmentsResponse, "no_response/models/operations/aggregateassessments_response.rb"
7
8
  autoload :AssociateCredentialRequest, "no_response/models/operations/associatecredential_request.rb"
8
9
  autoload :AssociateCredentialResponse, "no_response/models/operations/associatecredential_response.rb"
9
10
  autoload :BindProvisionalAccountRequest, "no_response/models/operations/bindprovisionalaccount_request.rb"
@@ -0,0 +1,73 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module NoResponse
5
+ module Models
6
+ module Shared
7
+
8
+ class AggregateBucket
9
+ extend T::Sig
10
+ include Crystalline::MetadataFields
11
+
12
+ field(
13
+ :start,
14
+ ::String,
15
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("start"), required: true}}
16
+ )
17
+ # Assessments first answered whose creation falls in the bucket. With metric count.
18
+ field(
19
+ :count,
20
+ Crystalline::Nilable.new(::Integer),
21
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("count")}}
22
+ )
23
+ # With metric count and group_by: the bucket's counts of the groups answered, largest group first.
24
+ field(
25
+ :groups,
26
+ Crystalline::Nilable.new(Crystalline::Array.new(Models::Shared::AggregateGroup)),
27
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("groups")}}
28
+ )
29
+
30
+ field(
31
+ :score_histogram,
32
+ Crystalline::Nilable.new(Crystalline::Array.new(Models::Shared::AggregateScoreCount)),
33
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("score_histogram")}}
34
+ )
35
+
36
+ field(
37
+ :late_flips,
38
+ Crystalline::Nilable.new(Crystalline::Array.new(Models::Shared::AggregateLateFlip)),
39
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("late_flips")}}
40
+ )
41
+
42
+ sig {
43
+ params(
44
+ start: ::String,
45
+ count: T.nilable(::Integer),
46
+ groups: T.nilable(T::Array[Models::Shared::AggregateGroup]),
47
+ score_histogram: T.nilable(T::Array[Models::Shared::AggregateScoreCount]),
48
+ late_flips: T.nilable(T::Array[Models::Shared::AggregateLateFlip])
49
+ )
50
+ .void
51
+ }
52
+ def initialize(start:, count: nil, groups: nil, score_histogram: nil, late_flips: nil)
53
+ @start = start
54
+ @count = count
55
+ @groups = groups
56
+ @score_histogram = score_histogram
57
+ @late_flips = late_flips
58
+ end
59
+
60
+ sig { params(other: T.untyped).returns(T::Boolean) }
61
+ def ==(other)
62
+ return false unless other.is_a?(self.class)
63
+ return false unless @start == other.start
64
+ return false unless @count == other.count
65
+ return false unless @groups == other.groups
66
+ return false unless @score_histogram == other.score_histogram
67
+ return false unless @late_flips == other.late_flips
68
+ true
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,38 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ class NoResponse::Models::Shared::AggregateBucket
5
+ extend ::Crystalline::MetadataFields::ClassMethods
6
+ end
7
+
8
+ class NoResponse::Models::Shared::AggregateBucket
9
+ def start
10
+ end
11
+
12
+ def start=(str_)
13
+ end
14
+
15
+ def count
16
+ end
17
+
18
+ def count=(str_)
19
+ end
20
+
21
+ def groups
22
+ end
23
+
24
+ def groups=(str_)
25
+ end
26
+
27
+ def score_histogram
28
+ end
29
+
30
+ def score_histogram=(str_)
31
+ end
32
+
33
+ def late_flips
34
+ end
35
+
36
+ def late_flips=(str_)
37
+ end
38
+ end
@@ -0,0 +1,26 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module NoResponse
5
+ module Models
6
+ module Shared
7
+ # AggregateDimension - decision, recommendation and band: the first answer's. flow: the assessment's. list_match: the action of the list entry that decided the account when it was first answered. reason: a reason the first answer fired, with its impact band. lane: an evidence lane the first answer listed in incomplete_sources. country and asn: the submitted IP's, from the IP data.
8
+ class AggregateDimension
9
+ include ::Crystalline::Enum
10
+ enums do
11
+ DECISION = new("decision")
12
+ FLOW = new("flow")
13
+ RECOMMENDATION = new("recommendation")
14
+ BAND = new("band")
15
+ REASON = new("reason")
16
+ LANE = new("lane")
17
+ COUNTRY = new("country")
18
+ ASN = new("asn")
19
+ LIST_MATCH = new("list_match")
20
+ end
21
+
22
+ open!
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ class NoResponse::Models::Shared::AggregateDimension
5
+ extend ::Crystalline::MetadataFields::ClassMethods
6
+ end
7
+
8
+ class NoResponse::Models::Shared::AggregateDimension
9
+ end