infrawrench-sdk 1.7.0 → 1.9.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.
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # infrawrench-sdk v1.7.0 | MIT | Copyright (c) 2026 Infrawrench LLC
3
+ # infrawrench-sdk v1.9.0 | MIT | Copyright (c) 2026 Infrawrench LLC
4
4
  # https://github.com/Infrawrench/Infrawrench
5
5
  #
6
- # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.7.0).
6
+ # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.9.0).
7
7
  #
8
8
  # DO NOT EDIT. Regenerate with:
9
9
  # pnpm --filter @infrawrench/web generate:sdk
@@ -1287,6 +1287,7 @@ module Infrawrench
1287
1287
  # @param action [String, nil]
1288
1288
  # @param entity_type [String, nil]
1289
1289
  # @param user_id [String, nil]
1290
+ # @param api_key_id [String, nil]
1290
1291
  # @param from [String, nil]
1291
1292
  # @param to [String, nil]
1292
1293
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
@@ -1299,6 +1300,7 @@ module Infrawrench
1299
1300
  action: nil,
1300
1301
  entity_type: nil,
1301
1302
  user_id: nil,
1303
+ api_key_id: nil,
1302
1304
  from: nil,
1303
1305
  to: nil,
1304
1306
  request_options: nil
@@ -1313,6 +1315,7 @@ module Infrawrench
1313
1315
  "action" => action,
1314
1316
  "entityType" => entity_type,
1315
1317
  "userId" => user_id,
1318
+ "apiKeyId" => api_key_id,
1316
1319
  "from" => from,
1317
1320
  "to" => to
1318
1321
  },
@@ -1568,6 +1571,159 @@ module Infrawrench
1568
1571
  end
1569
1572
  end
1570
1573
 
1574
+ # `client.billing_rules`
1575
+ class BillingRulesNamespace
1576
+ # @api private
1577
+ # @param transport [Transport]
1578
+ def initialize(transport)
1579
+ @transport = transport
1580
+ end
1581
+
1582
+ # Create a billing rule
1583
+ #
1584
+ # Requires `org:settings:write` rather than `costs:write`: a billing rule
1585
+ # changes every figure the organisation reports about itself, which is a
1586
+ # governance act on the scale of stating an exchange rate, not the scale of
1587
+ # saving a report.
1588
+ #
1589
+ # _Requires permission: `org:settings:write`._
1590
+ #
1591
+ # POST /api/org/{orgId}/billing-rules
1592
+ #
1593
+ # Raises on 400: Bad request
1594
+ #
1595
+ # Raises on 409: Conflict
1596
+ #
1597
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1598
+ # constructed with.
1599
+ # @param body [Hash] Request body, shaped as `BillingRuleInput`.
1600
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1601
+ # @return [Hash] Parsed JSON, shaped as `BillingRule` — see `sig/infrawrench/sdk.rbs`.
1602
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1603
+ def create(body:, org_id: nil, request_options: nil)
1604
+ @transport.request(
1605
+ http_method: "POST",
1606
+ path: "/api/org/{orgId}/billing-rules",
1607
+ path_params: { "orgId" => org_id },
1608
+ body: body,
1609
+ request_options: request_options
1610
+ )
1611
+ end
1612
+
1613
+ # Delete a billing rule
1614
+ #
1615
+ # Nothing cascades and nothing is restated: no adjustment was ever written
1616
+ # into stored cost data, so the next read simply computes without this rule.
1617
+ #
1618
+ # _Requires permission: `org:settings:write`._
1619
+ #
1620
+ # DELETE /api/org/{orgId}/billing-rules/{id}
1621
+ #
1622
+ # Raises on 404: Not found
1623
+ #
1624
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1625
+ # constructed with.
1626
+ # @param id [String]
1627
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1628
+ # @return [Hash] Parsed JSON, shaped as `Ok` — see `sig/infrawrench/sdk.rbs`.
1629
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1630
+ def delete(id:, org_id: nil, request_options: nil)
1631
+ @transport.request(
1632
+ http_method: "DELETE",
1633
+ path: "/api/org/{orgId}/billing-rules/{id}",
1634
+ path_params: { "orgId" => org_id, "id" => id },
1635
+ request_options: request_options
1636
+ )
1637
+ end
1638
+
1639
+ # Get a billing rule
1640
+ #
1641
+ # _Requires permission: `costs:read`._
1642
+ #
1643
+ # GET /api/org/{orgId}/billing-rules/{id}
1644
+ #
1645
+ # Raises on 404: Not found
1646
+ #
1647
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1648
+ # constructed with.
1649
+ # @param id [String]
1650
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1651
+ # @return [Hash] Parsed JSON, shaped as `BillingRule` — see `sig/infrawrench/sdk.rbs`.
1652
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1653
+ def get(id:, org_id: nil, request_options: nil)
1654
+ @transport.request(
1655
+ http_method: "GET",
1656
+ path: "/api/org/{orgId}/billing-rules/{id}",
1657
+ path_params: { "orgId" => org_id, "id" => id },
1658
+ request_options: request_options
1659
+ )
1660
+ end
1661
+
1662
+ # List billing rules in evaluation order
1663
+ #
1664
+ # Billing rules are the organisation's own adjustments to collected spend —
1665
+ # a markup that recovers shared overhead, a discount negotiated outside the
1666
+ # provider's pricing, a shared cluster reallocated onto the teams that use
1667
+ # it.
1668
+ #
1669
+ # **They are applied at query time and never written into stored cost
1670
+ # data.** Collected spend stays exactly what the provider reported, so it
1671
+ # can still be reconciled against an invoice, and editing or deleting a rule
1672
+ # restates nothing.
1673
+ #
1674
+ # _Requires permission: `costs:read`._
1675
+ #
1676
+ # GET /api/org/{orgId}/billing-rules
1677
+ #
1678
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1679
+ # constructed with.
1680
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1681
+ # @return [Array<Hash>] Parsed JSON, shaped as `Array<BillingRule>` — see
1682
+ # `sig/infrawrench/sdk.rbs`.
1683
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1684
+ def list(org_id: nil, request_options: nil)
1685
+ @transport.request(
1686
+ http_method: "GET",
1687
+ path: "/api/org/{orgId}/billing-rules",
1688
+ path_params: { "orgId" => org_id },
1689
+ request_options: request_options
1690
+ )
1691
+ end
1692
+
1693
+ # Update a billing rule
1694
+ #
1695
+ # A full replace, `enabled` included — switching a markup off is an edit of
1696
+ # the rule, so there is one audited action for “this rule changed” rather
1697
+ # than two.
1698
+ #
1699
+ # _Requires permission: `org:settings:write`._
1700
+ #
1701
+ # PUT /api/org/{orgId}/billing-rules/{id}
1702
+ #
1703
+ # Raises on 400: Bad request
1704
+ #
1705
+ # Raises on 404: Not found
1706
+ #
1707
+ # Raises on 409: Conflict
1708
+ #
1709
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1710
+ # constructed with.
1711
+ # @param id [String]
1712
+ # @param body [Hash] Request body, shaped as `BillingRuleInput`.
1713
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1714
+ # @return [Hash] Parsed JSON, shaped as `BillingRule` — see `sig/infrawrench/sdk.rbs`.
1715
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1716
+ def update(id:, body:, org_id: nil, request_options: nil)
1717
+ @transport.request(
1718
+ http_method: "PUT",
1719
+ path: "/api/org/{orgId}/billing-rules/{id}",
1720
+ path_params: { "orgId" => org_id, "id" => id },
1721
+ body: body,
1722
+ request_options: request_options
1723
+ )
1724
+ end
1725
+ end
1726
+
1571
1727
  # `client.budgets`
1572
1728
  class BudgetsNamespace
1573
1729
  # @api private
@@ -1707,6 +1863,286 @@ module Infrawrench
1707
1863
  end
1708
1864
  end
1709
1865
 
1866
+ # `client.business_metrics.get`
1867
+ class BusinessMetricsGetNamespace
1868
+ # @api private
1869
+ # @param transport [Transport]
1870
+ def initialize(transport)
1871
+ @transport = transport
1872
+ end
1873
+
1874
+ # List business metrics
1875
+ #
1876
+ # The organization's declared denominators, by key, each with the range of
1877
+ # days it has values for.
1878
+ #
1879
+ # _Requires permission: `costs:read`._
1880
+ #
1881
+ # GET /api/org/{orgId}/business-metrics
1882
+ #
1883
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1884
+ # constructed with.
1885
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1886
+ # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
1887
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1888
+ def get(org_id: nil, request_options: nil)
1889
+ @transport.request(
1890
+ http_method: "GET",
1891
+ path: "/api/org/{orgId}/business-metrics",
1892
+ path_params: { "orgId" => org_id },
1893
+ request_options: request_options
1894
+ )
1895
+ end
1896
+
1897
+ # Get a business metric
1898
+ #
1899
+ # `id` accepts either the metric's id or its key.
1900
+ #
1901
+ # _Requires permission: `costs:read`._
1902
+ #
1903
+ # GET /api/org/{orgId}/business-metrics/{id}
1904
+ #
1905
+ # Raises on 404: Not found
1906
+ #
1907
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1908
+ # constructed with.
1909
+ # @param id [String] Metric id or key
1910
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1911
+ # @return [Hash] Parsed JSON, shaped as `BusinessMetric` — see `sig/infrawrench/sdk.rbs`.
1912
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1913
+ def get_org_org_id_business_metrics_id(id:, org_id: nil, request_options: nil)
1914
+ @transport.request(
1915
+ http_method: "GET",
1916
+ path: "/api/org/{orgId}/business-metrics/{id}",
1917
+ path_params: { "orgId" => org_id, "id" => id },
1918
+ request_options: request_options
1919
+ )
1920
+ end
1921
+ end
1922
+
1923
+ # `client.business_metrics.values`
1924
+ class BusinessMetricsValuesNamespace
1925
+ # @api private
1926
+ # @param transport [Transport]
1927
+ def initialize(transport)
1928
+ @transport = transport
1929
+ end
1930
+
1931
+ # Report metric values
1932
+ #
1933
+ # Write a batch of days. **Re-reporting a day restates it rather than
1934
+ # accumulating**, which is what makes a nightly job safe to retry. Nothing
1935
+ # lands unless the whole batch validates, so a bad row is a 400 rather than
1936
+ # half a month restated. The same guarantees back
1937
+ # `infra.businessMetrics.write(...)` in a workflow — both go through one
1938
+ # validator.
1939
+ #
1940
+ # _Requires permission: `costs:write`._
1941
+ #
1942
+ # POST /api/org/{orgId}/business-metrics/{id}/values
1943
+ #
1944
+ # Raises on 400: Bad request
1945
+ #
1946
+ # Raises on 404: Not found
1947
+ #
1948
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1949
+ # constructed with.
1950
+ # @param id [String] Metric id or key
1951
+ # @param body [Hash] Request body, shaped as `BusinessMetricValuesInput`.
1952
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1953
+ # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
1954
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1955
+ def create(id:, body:, org_id: nil, request_options: nil)
1956
+ @transport.request(
1957
+ http_method: "POST",
1958
+ path: "/api/org/{orgId}/business-metrics/{id}/values",
1959
+ path_params: { "orgId" => org_id, "id" => id },
1960
+ body: body,
1961
+ request_options: request_options
1962
+ )
1963
+ end
1964
+
1965
+ # List a metric's reported values
1966
+ #
1967
+ # Newest day first.
1968
+ #
1969
+ # _Requires permission: `costs:read`._
1970
+ #
1971
+ # GET /api/org/{orgId}/business-metrics/{id}/values
1972
+ #
1973
+ # Raises on 400: Bad request
1974
+ #
1975
+ # Raises on 404: Not found
1976
+ #
1977
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
1978
+ # constructed with.
1979
+ # @param id [String] Metric id or key
1980
+ # @param limit [Integer, nil] Default 90.
1981
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
1982
+ # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
1983
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
1984
+ def get(id:, org_id: nil, limit: nil, request_options: nil)
1985
+ @transport.request(
1986
+ http_method: "GET",
1987
+ path: "/api/org/{orgId}/business-metrics/{id}/values",
1988
+ path_params: { "orgId" => org_id, "id" => id },
1989
+ query: { "limit" => limit },
1990
+ request_options: request_options
1991
+ )
1992
+ end
1993
+ end
1994
+
1995
+ # `client.business_metrics`
1996
+ class BusinessMetricsNamespace
1997
+ # @return [BusinessMetricsGetNamespace] `client.business_metrics.get`
1998
+ attr_reader :get
1999
+ # @return [BusinessMetricsValuesNamespace] `client.business_metrics.values`
2000
+ attr_reader :values
2001
+
2002
+ # @api private
2003
+ # @param transport [Transport]
2004
+ def initialize(transport)
2005
+ @transport = transport
2006
+ @get = BusinessMetricsGetNamespace.new(@transport)
2007
+ @values = BusinessMetricsValuesNamespace.new(@transport)
2008
+ end
2009
+
2010
+ # Create a business metric
2011
+ #
2012
+ # Keys must be unique per organization among live metrics — they are how
2013
+ # workflows and the CLI address the metric. A key collision is a 409.
2014
+ #
2015
+ # _Requires permission: `costs:write`._
2016
+ #
2017
+ # POST /api/org/{orgId}/business-metrics
2018
+ #
2019
+ # Raises on 400: Bad request
2020
+ #
2021
+ # Raises on 409: A live metric already uses this key.
2022
+ #
2023
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2024
+ # constructed with.
2025
+ # @param body [Hash] Request body, shaped as `BusinessMetricInput`.
2026
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2027
+ # @return [Hash] Parsed JSON, shaped as `BusinessMetric` — see `sig/infrawrench/sdk.rbs`.
2028
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
2029
+ def create(body:, org_id: nil, request_options: nil)
2030
+ @transport.request(
2031
+ http_method: "POST",
2032
+ path: "/api/org/{orgId}/business-metrics",
2033
+ path_params: { "orgId" => org_id },
2034
+ body: body,
2035
+ request_options: request_options
2036
+ )
2037
+ end
2038
+
2039
+ # Delete a business metric
2040
+ #
2041
+ # Soft delete. Not refused when a dashboard card references the metric,
2042
+ # unlike a saved cost filter: a unit-cost card whose metric is gone fails
2043
+ # its query and says so, whereas a card that quietly reverted to plain spend
2044
+ # would be a chart claiming to be something it is not.
2045
+ #
2046
+ # _Requires permission: `costs:write`._
2047
+ #
2048
+ # DELETE /api/org/{orgId}/business-metrics/{id}
2049
+ #
2050
+ # Raises on 404: Not found
2051
+ #
2052
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2053
+ # constructed with.
2054
+ # @param id [String] Metric id or key
2055
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2056
+ # @return [Hash] Parsed JSON, shaped as `Ok` — see `sig/infrawrench/sdk.rbs`.
2057
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
2058
+ def delete(id:, org_id: nil, request_options: nil)
2059
+ @transport.request(
2060
+ http_method: "DELETE",
2061
+ path: "/api/org/{orgId}/business-metrics/{id}",
2062
+ path_params: { "orgId" => org_id, "id" => id },
2063
+ request_options: request_options
2064
+ )
2065
+ end
2066
+
2067
+ # Query unit costs or margin
2068
+ #
2069
+ # Divide spend by the metric, bucketed as asked. Three properties of the
2070
+ # answer are worth knowing before reading it:
2071
+ #
2072
+ # - **The ratio is computed at the requested bucket**, from a summed
2073
+ # numerator and a summed denominator — never a mean of daily ratios, which
2074
+ # weights a quiet day as heavily as a peak one. The same holds for
2075
+ # `overallValue`.
2076
+ # - **A missing or non-positive denominator is a gap** (`value: null` with a
2077
+ # `gap` reason), never 0 and never infinite.
2078
+ # - **Currencies are never merged.** Spend in a currency with no stated rate
2079
+ # keeps its own series rather than being dropped or added to another.
2080
+ #
2081
+ # There is no `groupBy`: a per-group ratio would need a per-group
2082
+ # denominator, and dividing each service's spend by the whole customer count
2083
+ # produces numbers that do not sum to the real one.
2084
+ #
2085
+ # _Requires permission: `costs:read`._
2086
+ #
2087
+ # POST /api/org/{orgId}/business-metrics/{id}/unit-costs
2088
+ #
2089
+ # Raises on 400: Bad request
2090
+ #
2091
+ # Raises on 404: Not found
2092
+ #
2093
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2094
+ # constructed with.
2095
+ # @param id [String] Metric id or key
2096
+ # @param body [Hash] Request body, shaped as `UnitCostQueryRequest`.
2097
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2098
+ # @return [Hash] Parsed JSON, shaped as `UnitCostQueryResponse` — see
2099
+ # `sig/infrawrench/sdk.rbs`.
2100
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
2101
+ def unit_costs(id:, body:, org_id: nil, request_options: nil)
2102
+ @transport.request(
2103
+ http_method: "POST",
2104
+ path: "/api/org/{orgId}/business-metrics/{id}/unit-costs",
2105
+ path_params: { "orgId" => org_id, "id" => id },
2106
+ body: body,
2107
+ request_options: request_options
2108
+ )
2109
+ end
2110
+
2111
+ # Update a business metric
2112
+ #
2113
+ # Replaces the whole definition. Changing `key` never orphans history —
2114
+ # values are keyed on the metric's id — but it does break a workflow still
2115
+ # writing to the old key, which is why the key is separate from the display
2116
+ # name in the first place.
2117
+ #
2118
+ # _Requires permission: `costs:write`._
2119
+ #
2120
+ # PUT /api/org/{orgId}/business-metrics/{id}
2121
+ #
2122
+ # Raises on 400: Bad request
2123
+ #
2124
+ # Raises on 404: Not found
2125
+ #
2126
+ # Raises on 409: A live metric already uses this key.
2127
+ #
2128
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2129
+ # constructed with.
2130
+ # @param id [String] Metric id or key
2131
+ # @param body [Hash] Request body, shaped as `BusinessMetricInput`.
2132
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2133
+ # @return [Hash] Parsed JSON, shaped as `BusinessMetric` — see `sig/infrawrench/sdk.rbs`.
2134
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
2135
+ def update(id:, body:, org_id: nil, request_options: nil)
2136
+ @transport.request(
2137
+ http_method: "PUT",
2138
+ path: "/api/org/{orgId}/business-metrics/{id}",
2139
+ path_params: { "orgId" => org_id, "id" => id },
2140
+ body: body,
2141
+ request_options: request_options
2142
+ )
2143
+ end
2144
+ end
2145
+
1710
2146
  # `client.change_freezes`
1711
2147
  class ChangeFreezesNamespace
1712
2148
  # @api private
@@ -2291,89 +2727,205 @@ module Infrawrench
2291
2727
  #
2292
2728
  # _Requires permission: `costs:read`._
2293
2729
  #
2294
- # GET /api/org/{orgId}/cost-alerts
2730
+ # GET /api/org/{orgId}/cost-alerts
2731
+ #
2732
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2733
+ # constructed with.
2734
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2735
+ # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
2736
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
2737
+ def get(org_id: nil, request_options: nil)
2738
+ @transport.request(
2739
+ http_method: "GET",
2740
+ path: "/api/org/{orgId}/cost-alerts",
2741
+ path_params: { "orgId" => org_id },
2742
+ request_options: request_options
2743
+ )
2744
+ end
2745
+
2746
+ # Get a cost alert
2747
+ #
2748
+ # _Requires permission: `costs:read`._
2749
+ #
2750
+ # GET /api/org/{orgId}/cost-alerts/{id}
2751
+ #
2752
+ # Raises on 404: Not found
2753
+ #
2754
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2755
+ # constructed with.
2756
+ # @param id [String]
2757
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2758
+ # @return [Hash] Parsed JSON, shaped as `CostAlert` — see `sig/infrawrench/sdk.rbs`.
2759
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
2760
+ def get_org_org_id_cost_alerts_id(id:, org_id: nil, request_options: nil)
2761
+ @transport.request(
2762
+ http_method: "GET",
2763
+ path: "/api/org/{orgId}/cost-alerts/{id}",
2764
+ path_params: { "orgId" => org_id, "id" => id },
2765
+ request_options: request_options
2766
+ )
2767
+ end
2768
+ end
2769
+
2770
+ # `client.cost_alerts`
2771
+ class CostAlertsNamespace
2772
+ # @return [CostAlertsGetNamespace] `client.cost_alerts.get`
2773
+ attr_reader :get
2774
+
2775
+ # @api private
2776
+ # @param transport [Transport]
2777
+ def initialize(transport)
2778
+ @transport = transport
2779
+ @get = CostAlertsGetNamespace.new(@transport)
2780
+ end
2781
+
2782
+ # Create a change-based cost alert
2783
+ #
2784
+ # _Requires permission: `costs:write`._
2785
+ #
2786
+ # POST /api/org/{orgId}/cost-alerts
2787
+ #
2788
+ # Raises on 400: Bad request
2789
+ #
2790
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2791
+ # constructed with.
2792
+ # @param body [Hash] Request body, shaped as `CostAlertInput`.
2793
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2794
+ # @return [Hash] Parsed JSON, shaped as `CostAlert` — see `sig/infrawrench/sdk.rbs`.
2795
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
2796
+ def create(body:, org_id: nil, request_options: nil)
2797
+ @transport.request(
2798
+ http_method: "POST",
2799
+ path: "/api/org/{orgId}/cost-alerts",
2800
+ path_params: { "orgId" => org_id },
2801
+ body: body,
2802
+ request_options: request_options
2803
+ )
2804
+ end
2805
+
2806
+ # Delete a cost alert
2807
+ #
2808
+ # Soft delete. Fired events disappear from the org-wide event feed with it.
2809
+ #
2810
+ # _Requires permission: `costs:write`._
2811
+ #
2812
+ # DELETE /api/org/{orgId}/cost-alerts/{id}
2813
+ #
2814
+ # Raises on 404: Not found
2815
+ #
2816
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2817
+ # constructed with.
2818
+ # @param id [String]
2819
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2820
+ # @return [Hash] Parsed JSON, shaped as `Ok` — see `sig/infrawrench/sdk.rbs`.
2821
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
2822
+ def delete(id:, org_id: nil, request_options: nil)
2823
+ @transport.request(
2824
+ http_method: "DELETE",
2825
+ path: "/api/org/{orgId}/cost-alerts/{id}",
2826
+ path_params: { "orgId" => org_id, "id" => id },
2827
+ request_options: request_options
2828
+ )
2829
+ end
2830
+
2831
+ # List recently fired cost-alert events
2832
+ #
2833
+ # Newest first. Optionally scoped to one alert with ?alertId=; an unknown
2834
+ # alertId is a 404, distinct from an alert that simply has no events yet.
2835
+ #
2836
+ # _Requires permission: `costs:read`._
2837
+ #
2838
+ # GET /api/org/{orgId}/cost-alerts/events
2839
+ #
2840
+ # Raises on 400: Bad request
2841
+ #
2842
+ # Raises on 404: Not found
2295
2843
  #
2296
2844
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2297
2845
  # constructed with.
2846
+ # @param alert_id [String, nil]
2847
+ # @param limit [Integer, nil]
2298
2848
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2299
2849
  # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
2300
2850
  # @raise [Infrawrench::ApiError] On any non-2xx response.
2301
- def get(org_id: nil, request_options: nil)
2851
+ def events(org_id: nil, alert_id: nil, limit: nil, request_options: nil)
2302
2852
  @transport.request(
2303
2853
  http_method: "GET",
2304
- path: "/api/org/{orgId}/cost-alerts",
2854
+ path: "/api/org/{orgId}/cost-alerts/events",
2305
2855
  path_params: { "orgId" => org_id },
2856
+ query: { "alertId" => alert_id, "limit" => limit },
2306
2857
  request_options: request_options
2307
2858
  )
2308
2859
  end
2309
2860
 
2310
- # Get a cost alert
2861
+ # Update a cost alert
2311
2862
  #
2312
- # _Requires permission: `costs:read`._
2863
+ # _Requires permission: `costs:write`._
2313
2864
  #
2314
- # GET /api/org/{orgId}/cost-alerts/{id}
2865
+ # PUT /api/org/{orgId}/cost-alerts/{id}
2866
+ #
2867
+ # Raises on 400: Bad request
2315
2868
  #
2316
2869
  # Raises on 404: Not found
2317
2870
  #
2318
2871
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2319
2872
  # constructed with.
2320
2873
  # @param id [String]
2874
+ # @param body [Hash] Request body, shaped as `CostAlertInput`.
2321
2875
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2322
2876
  # @return [Hash] Parsed JSON, shaped as `CostAlert` — see `sig/infrawrench/sdk.rbs`.
2323
2877
  # @raise [Infrawrench::ApiError] On any non-2xx response.
2324
- def get_org_org_id_cost_alerts_id(id:, org_id: nil, request_options: nil)
2878
+ def update(id:, body:, org_id: nil, request_options: nil)
2325
2879
  @transport.request(
2326
- http_method: "GET",
2880
+ http_method: "PUT",
2327
2881
  path: "/api/org/{orgId}/cost-alerts/{id}",
2328
2882
  path_params: { "orgId" => org_id, "id" => id },
2883
+ body: body,
2329
2884
  request_options: request_options
2330
2885
  )
2331
2886
  end
2332
2887
  end
2333
2888
 
2334
- # `client.cost_alerts`
2335
- class CostAlertsNamespace
2336
- # @return [CostAlertsGetNamespace] `client.cost_alerts.get`
2337
- attr_reader :get
2338
-
2889
+ # `client.cost_annotations`
2890
+ class CostAnnotationsNamespace
2339
2891
  # @api private
2340
2892
  # @param transport [Transport]
2341
2893
  def initialize(transport)
2342
2894
  @transport = transport
2343
- @get = CostAlertsGetNamespace.new(@transport)
2344
2895
  end
2345
2896
 
2346
- # Create a change-based cost alert
2897
+ # Create a cost annotation
2347
2898
  #
2348
2899
  # _Requires permission: `costs:write`._
2349
2900
  #
2350
- # POST /api/org/{orgId}/cost-alerts
2901
+ # POST /api/org/{orgId}/cost-annotations
2351
2902
  #
2352
2903
  # Raises on 400: Bad request
2353
2904
  #
2354
2905
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2355
2906
  # constructed with.
2356
- # @param body [Hash] Request body, shaped as `CostAlertInput`.
2907
+ # @param body [Hash] Request body, shaped as `CostAnnotationInput`.
2357
2908
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2358
- # @return [Hash] Parsed JSON, shaped as `CostAlert` — see `sig/infrawrench/sdk.rbs`.
2909
+ # @return [Hash] Parsed JSON, shaped as `CostAnnotation` — see `sig/infrawrench/sdk.rbs`.
2359
2910
  # @raise [Infrawrench::ApiError] On any non-2xx response.
2360
2911
  def create(body:, org_id: nil, request_options: nil)
2361
2912
  @transport.request(
2362
2913
  http_method: "POST",
2363
- path: "/api/org/{orgId}/cost-alerts",
2914
+ path: "/api/org/{orgId}/cost-annotations",
2364
2915
  path_params: { "orgId" => org_id },
2365
2916
  body: body,
2366
2917
  request_options: request_options
2367
2918
  )
2368
2919
  end
2369
2920
 
2370
- # Delete a cost alert
2921
+ # Delete a cost annotation
2371
2922
  #
2372
- # Soft delete. Fired events disappear from the org-wide event feed with it.
2923
+ # A hard delete. A withdrawn explanation should stop being drawn, and
2924
+ # nothing references a note by id.
2373
2925
  #
2374
2926
  # _Requires permission: `costs:write`._
2375
2927
  #
2376
- # DELETE /api/org/{orgId}/cost-alerts/{id}
2928
+ # DELETE /api/org/{orgId}/cost-annotations/{id}
2377
2929
  #
2378
2930
  # Raises on 404: Not found
2379
2931
  #
@@ -2386,47 +2938,47 @@ module Infrawrench
2386
2938
  def delete(id:, org_id: nil, request_options: nil)
2387
2939
  @transport.request(
2388
2940
  http_method: "DELETE",
2389
- path: "/api/org/{orgId}/cost-alerts/{id}",
2941
+ path: "/api/org/{orgId}/cost-annotations/{id}",
2390
2942
  path_params: { "orgId" => org_id, "id" => id },
2391
2943
  request_options: request_options
2392
2944
  )
2393
2945
  end
2394
2946
 
2395
- # List recently fired cost-alert events
2947
+ # List cost annotations
2396
2948
  #
2397
- # Newest first. Optionally scoped to one alert with ?alertId=; an unknown
2398
- # alertId is a 404, distinct from an alert that simply has no events yet.
2949
+ # Dated notes drawn over cost charts. With `reportId`, the set a chart for
2950
+ # that report draws: the org-wide notes plus that report's own. Without it,
2951
+ # every annotation in the org. Annotations are an overlay — they never
2952
+ # appear in a series, a total, or an axis.
2399
2953
  #
2400
2954
  # _Requires permission: `costs:read`._
2401
2955
  #
2402
- # GET /api/org/{orgId}/cost-alerts/events
2403
- #
2404
- # Raises on 400: Bad request
2405
- #
2406
- # Raises on 404: Not found
2956
+ # GET /api/org/{orgId}/cost-annotations
2407
2957
  #
2408
2958
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2409
2959
  # constructed with.
2410
- # @param alert_id [String, nil]
2411
- # @param limit [Integer, nil]
2960
+ # @param report_id [String, nil] Scope to the notes a chart for this report should draw.
2412
2961
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2413
2962
  # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
2414
2963
  # @raise [Infrawrench::ApiError] On any non-2xx response.
2415
- def events(org_id: nil, alert_id: nil, limit: nil, request_options: nil)
2964
+ def get(org_id: nil, report_id: nil, request_options: nil)
2416
2965
  @transport.request(
2417
2966
  http_method: "GET",
2418
- path: "/api/org/{orgId}/cost-alerts/events",
2967
+ path: "/api/org/{orgId}/cost-annotations",
2419
2968
  path_params: { "orgId" => org_id },
2420
- query: { "alertId" => alert_id, "limit" => limit },
2969
+ query: { "reportId" => report_id },
2421
2970
  request_options: request_options
2422
2971
  )
2423
2972
  end
2424
2973
 
2425
- # Update a cost alert
2974
+ # Update a cost annotation
2975
+ #
2976
+ # Replaces the note's dates, text and scope. Moving a note between org-wide
2977
+ # and one report is this same PUT with a different `costReportId`.
2426
2978
  #
2427
2979
  # _Requires permission: `costs:write`._
2428
2980
  #
2429
- # PUT /api/org/{orgId}/cost-alerts/{id}
2981
+ # PUT /api/org/{orgId}/cost-annotations/{id}
2430
2982
  #
2431
2983
  # Raises on 400: Bad request
2432
2984
  #
@@ -2435,14 +2987,14 @@ module Infrawrench
2435
2987
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
2436
2988
  # constructed with.
2437
2989
  # @param id [String]
2438
- # @param body [Hash] Request body, shaped as `CostAlertInput`.
2990
+ # @param body [Hash] Request body, shaped as `CostAnnotationInput`.
2439
2991
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
2440
- # @return [Hash] Parsed JSON, shaped as `CostAlert` — see `sig/infrawrench/sdk.rbs`.
2992
+ # @return [Hash] Parsed JSON, shaped as `CostAnnotation` — see `sig/infrawrench/sdk.rbs`.
2441
2993
  # @raise [Infrawrench::ApiError] On any non-2xx response.
2442
2994
  def update(id:, body:, org_id: nil, request_options: nil)
2443
2995
  @transport.request(
2444
2996
  http_method: "PUT",
2445
- path: "/api/org/{orgId}/cost-alerts/{id}",
2997
+ path: "/api/org/{orgId}/cost-annotations/{id}",
2446
2998
  path_params: { "orgId" => org_id, "id" => id },
2447
2999
  body: body,
2448
3000
  request_options: request_options
@@ -2628,6 +3180,12 @@ module Infrawrench
2628
3180
 
2629
3181
  # Delete a cost centre (its allocation rules go with it)
2630
3182
  #
3183
+ # The centre's allocation rules are deleted with it, so the spend they
3184
+ # claimed falls through to the next matching rule or to "Unallocated". Child
3185
+ # centres are not deleted: they are re-parented onto the deleted centre's
3186
+ # own parent (a root's children become roots), so a subtree keeps its shape
3187
+ # and no ancestor's subtree total moves unexpectedly.
3188
+ #
2631
3189
  # _Requires permission: `costs:write`._
2632
3190
  #
2633
3191
  # DELETE /api/org/{orgId}/cost-centres/{id}
@@ -2670,7 +3228,11 @@ module Infrawrench
2670
3228
  )
2671
3229
  end
2672
3230
 
2673
- # Update a cost centre
3231
+ # Update or move a cost centre
3232
+ #
3233
+ # Renames, redescribes, and/or moves a centre. Moving is `parentId`
3234
+ # changing; omitting the field leaves the centre where it is. 400 when the
3235
+ # move would cycle or breach the depth cap.
2674
3236
  #
2675
3237
  # _Requires permission: `costs:write`._
2676
3238
  #
@@ -3370,6 +3932,203 @@ module Infrawrench
3370
3932
  end
3371
3933
  end
3372
3934
 
3935
+ # `client.cost_scenarios.get`
3936
+ class CostScenariosGetNamespace
3937
+ # @api private
3938
+ # @param transport [Transport]
3939
+ def initialize(transport)
3940
+ @transport = transport
3941
+ end
3942
+
3943
+ # List scenario models
3944
+ #
3945
+ # Named, reusable sets of adjustments an organization overlays on a cost
3946
+ # forecast — the **known future cost a trend fit cannot see**. Pass an id as
3947
+ # `POST /costs/query`'s `scenarioModelId` (alongside `forecast: true`) to
3948
+ # get the adjusted projection back *beside* the unadjusted one, never
3949
+ # instead of it.
3950
+ #
3951
+ # _Requires permission: `costs:read`._
3952
+ #
3953
+ # GET /api/org/{orgId}/cost-scenarios
3954
+ #
3955
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
3956
+ # constructed with.
3957
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
3958
+ # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
3959
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
3960
+ def get(org_id: nil, request_options: nil)
3961
+ @transport.request(
3962
+ http_method: "GET",
3963
+ path: "/api/org/{orgId}/cost-scenarios",
3964
+ path_params: { "orgId" => org_id },
3965
+ request_options: request_options
3966
+ )
3967
+ end
3968
+
3969
+ # Get a scenario model
3970
+ #
3971
+ # _Requires permission: `costs:read`._
3972
+ #
3973
+ # GET /api/org/{orgId}/cost-scenarios/{id}
3974
+ #
3975
+ # Raises on 404: Not found
3976
+ #
3977
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
3978
+ # constructed with.
3979
+ # @param id [String]
3980
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
3981
+ # @return [Hash] Parsed JSON, shaped as `CostScenarioModel` — see `sig/infrawrench/sdk.rbs`.
3982
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
3983
+ def get_org_org_id_cost_scenarios_id(id:, org_id: nil, request_options: nil)
3984
+ @transport.request(
3985
+ http_method: "GET",
3986
+ path: "/api/org/{orgId}/cost-scenarios/{id}",
3987
+ path_params: { "orgId" => org_id, "id" => id },
3988
+ request_options: request_options
3989
+ )
3990
+ end
3991
+ end
3992
+
3993
+ # `client.cost_scenarios`
3994
+ class CostScenariosNamespace
3995
+ # @return [CostScenariosGetNamespace] `client.cost_scenarios.get`
3996
+ attr_reader :get
3997
+
3998
+ # @api private
3999
+ # @param transport [Transport]
4000
+ def initialize(transport)
4001
+ @transport = transport
4002
+ @get = CostScenariosGetNamespace.new(@transport)
4003
+ end
4004
+
4005
+ # Create a scenario model
4006
+ #
4007
+ # Names must be unique per organization (case-insensitively) — the name is
4008
+ # what a chart prints under its scenario line and what the CLI's `--scenario
4009
+ # <name>` addresses, so two models sharing one would make both meaningless.
4010
+ # A model needs at least one adjustment: an empty model changes nothing,
4011
+ # which is the same as applying no scenario.
4012
+ #
4013
+ # _Requires permission: `costs:write`._
4014
+ #
4015
+ # POST /api/org/{orgId}/cost-scenarios
4016
+ #
4017
+ # Raises on 400: Bad request
4018
+ #
4019
+ # Raises on 409: A live scenario model already uses this name.
4020
+ #
4021
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
4022
+ # constructed with.
4023
+ # @param body [Hash] Request body, shaped as `CostScenarioModelInput`.
4024
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
4025
+ # @return [Hash] Parsed JSON, shaped as `CostScenarioModel` — see `sig/infrawrench/sdk.rbs`.
4026
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
4027
+ def create(body:, org_id: nil, request_options: nil)
4028
+ @transport.request(
4029
+ http_method: "POST",
4030
+ path: "/api/org/{orgId}/cost-scenarios",
4031
+ path_params: { "orgId" => org_id },
4032
+ body: body,
4033
+ request_options: request_options
4034
+ )
4035
+ end
4036
+
4037
+ # Delete a scenario model
4038
+ #
4039
+ # Soft delete — **refused with a 409 while anything references the model**,
4040
+ # with the referents in the body. For a chart, deleting would silently drop
4041
+ # the assumptions from a projection somebody is reading; for a budget it
4042
+ # would move the forecast thresholds back to the bare trend, changing when
4043
+ # people get paged. Detaching the referents is a deliberate step, never a
4044
+ # side effect of deletion.
4045
+ #
4046
+ # _Requires permission: `costs:write`._
4047
+ #
4048
+ # DELETE /api/org/{orgId}/cost-scenarios/{id}
4049
+ #
4050
+ # Raises on 404: Not found
4051
+ #
4052
+ # Raises on 409: Still referenced — the body lists every referent.
4053
+ #
4054
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
4055
+ # constructed with.
4056
+ # @param id [String]
4057
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
4058
+ # @return [Hash] Parsed JSON, shaped as `Ok` — see `sig/infrawrench/sdk.rbs`.
4059
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
4060
+ def delete(id:, org_id: nil, request_options: nil)
4061
+ @transport.request(
4062
+ http_method: "DELETE",
4063
+ path: "/api/org/{orgId}/cost-scenarios/{id}",
4064
+ path_params: { "orgId" => org_id, "id" => id },
4065
+ request_options: request_options
4066
+ )
4067
+ end
4068
+
4069
+ # List a scenario model's referents
4070
+ #
4071
+ # Every budget, cost report and dashboard cost graph referencing this model
4072
+ # — what an edit will change, and what a delete would be refused over.
4073
+ # Budgets come first: they are the referents that page people.
4074
+ #
4075
+ # _Requires permission: `costs:read`._
4076
+ #
4077
+ # GET /api/org/{orgId}/cost-scenarios/{id}/referents
4078
+ #
4079
+ # Raises on 404: Not found
4080
+ #
4081
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
4082
+ # constructed with.
4083
+ # @param id [String]
4084
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
4085
+ # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
4086
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
4087
+ def referents(id:, org_id: nil, request_options: nil)
4088
+ @transport.request(
4089
+ http_method: "GET",
4090
+ path: "/api/org/{orgId}/cost-scenarios/{id}/referents",
4091
+ path_params: { "orgId" => org_id, "id" => id },
4092
+ request_options: request_options
4093
+ )
4094
+ end
4095
+
4096
+ # Update a scenario model
4097
+ #
4098
+ # Replaces the whole model. This is the high-leverage write: every chart
4099
+ # drawing it, and **every budget whose forecast thresholds are measured
4100
+ # against it**, uses the new numbers on its next evaluation — which for a
4101
+ # budget can change which alerts fire. `GET /{id}/referents` names what a
4102
+ # change will touch.
4103
+ #
4104
+ # _Requires permission: `costs:write`._
4105
+ #
4106
+ # PUT /api/org/{orgId}/cost-scenarios/{id}
4107
+ #
4108
+ # Raises on 400: Bad request
4109
+ #
4110
+ # Raises on 404: Not found
4111
+ #
4112
+ # Raises on 409: A live scenario model already uses this name.
4113
+ #
4114
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
4115
+ # constructed with.
4116
+ # @param id [String]
4117
+ # @param body [Hash] Request body, shaped as `CostScenarioModelInput`.
4118
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
4119
+ # @return [Hash] Parsed JSON, shaped as `CostScenarioModel` — see `sig/infrawrench/sdk.rbs`.
4120
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
4121
+ def update(id:, body:, org_id: nil, request_options: nil)
4122
+ @transport.request(
4123
+ http_method: "PUT",
4124
+ path: "/api/org/{orgId}/cost-scenarios/{id}",
4125
+ path_params: { "orgId" => org_id, "id" => id },
4126
+ body: body,
4127
+ request_options: request_options
4128
+ )
4129
+ end
4130
+ end
4131
+
3373
4132
  # `client.costs.anomaly_settings`
3374
4133
  class CostsAnomalySettingsNamespace
3375
4134
  # @api private
@@ -3424,13 +4183,78 @@ module Infrawrench
3424
4183
  # constructed with.
3425
4184
  # @param body [Hash] Request body, shaped as `CostAnomalySettings`.
3426
4185
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
3427
- # @return [Hash] Parsed JSON, shaped as `CostAnomalySettingsView` — see
4186
+ # @return [Hash] Parsed JSON, shaped as `CostAnomalySettingsView` — see
4187
+ # `sig/infrawrench/sdk.rbs`.
4188
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
4189
+ def update(body:, org_id: nil, request_options: nil)
4190
+ @transport.request(
4191
+ http_method: "PUT",
4192
+ path: "/api/org/{orgId}/costs/anomaly-settings",
4193
+ path_params: { "orgId" => org_id },
4194
+ body: body,
4195
+ request_options: request_options
4196
+ )
4197
+ end
4198
+ end
4199
+
4200
+ # `client.costs.efficiency_alert_settings`
4201
+ class CostsEfficiencyAlertSettingsNamespace
4202
+ # @api private
4203
+ # @param transport [Transport]
4204
+ def initialize(transport)
4205
+ @transport = transport
4206
+ end
4207
+
4208
+ # Get the organization's efficiency alert tuning
4209
+ #
4210
+ # Thresholds for the commitment-expiry, idle-commitment and
4211
+ # unit-cost-regression detectors. An organization that has never changed one
4212
+ # reads back the defaults, which are chosen to work with no setup.
4213
+ #
4214
+ # _Requires permission: `costs:read`._
4215
+ #
4216
+ # GET /api/org/{orgId}/costs/efficiency-alert-settings
4217
+ #
4218
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
4219
+ # constructed with.
4220
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
4221
+ # @return [Hash] Parsed JSON, shaped as `CostEfficiencySettings` — see
4222
+ # `sig/infrawrench/sdk.rbs`.
4223
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
4224
+ def get(org_id: nil, request_options: nil)
4225
+ @transport.request(
4226
+ http_method: "GET",
4227
+ path: "/api/org/{orgId}/costs/efficiency-alert-settings",
4228
+ path_params: { "orgId" => org_id },
4229
+ request_options: request_options
4230
+ )
4231
+ end
4232
+
4233
+ # Update the organization's efficiency alert tuning
4234
+ #
4235
+ # Takes effect on the next evaluation pass (which runs after each cost
4236
+ # collection). Already-fired alerts are not re-judged, and horizons that
4237
+ # have already fired for a commitment's current term do not fire again —
4238
+ # widening the horizon list warns about future crossings, not past ones. A
4239
+ # PUT of the whole object, not a patch.
4240
+ #
4241
+ # _Requires permission: `costs:write`._
4242
+ #
4243
+ # PUT /api/org/{orgId}/costs/efficiency-alert-settings
4244
+ #
4245
+ # Raises on 400: Bad request
4246
+ #
4247
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
4248
+ # constructed with.
4249
+ # @param body [Hash] Request body, shaped as `CostEfficiencySettings`.
4250
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
4251
+ # @return [Hash] Parsed JSON, shaped as `CostEfficiencySettings` — see
3428
4252
  # `sig/infrawrench/sdk.rbs`.
3429
4253
  # @raise [Infrawrench::ApiError] On any non-2xx response.
3430
4254
  def update(body:, org_id: nil, request_options: nil)
3431
4255
  @transport.request(
3432
4256
  http_method: "PUT",
3433
- path: "/api/org/{orgId}/costs/anomaly-settings",
4257
+ path: "/api/org/{orgId}/costs/efficiency-alert-settings",
3434
4258
  path_params: { "orgId" => org_id },
3435
4259
  body: body,
3436
4260
  request_options: request_options
@@ -3442,12 +4266,15 @@ module Infrawrench
3442
4266
  class CostsNamespace
3443
4267
  # @return [CostsAnomalySettingsNamespace] `client.costs.anomaly_settings`
3444
4268
  attr_reader :anomaly_settings
4269
+ # @return [CostsEfficiencyAlertSettingsNamespace] `client.costs.efficiency_alert_settings`
4270
+ attr_reader :efficiency_alert_settings
3445
4271
 
3446
4272
  # @api private
3447
4273
  # @param transport [Transport]
3448
4274
  def initialize(transport)
3449
4275
  @transport = transport
3450
4276
  @anomaly_settings = CostsAnomalySettingsNamespace.new(@transport)
4277
+ @efficiency_alert_settings = CostsEfficiencyAlertSettingsNamespace.new(@transport)
3451
4278
  end
3452
4279
 
3453
4280
  # List recently detected cost anomalies
@@ -3513,6 +4340,39 @@ module Infrawrench
3513
4340
  )
3514
4341
  end
3515
4342
 
4343
+ # Recently fired efficiency alerts
4344
+ #
4345
+ # The three slow-lane cost alerts in one feed, newest first: commitments
4346
+ # about to lapse, commitments that are not being used, and business metrics
4347
+ # whose cost per unit rose. Unlike budgets, anomalies and change alerts —
4348
+ # all of which compare a spend total against another spend total — these
4349
+ # read the commitment calendar and the volume the spend bought, so they see
4350
+ # the two surprises the other three structurally cannot.
4351
+ #
4352
+ # _Requires permission: `costs:read`._
4353
+ #
4354
+ # GET /api/org/{orgId}/costs/efficiency-alerts
4355
+ #
4356
+ # Raises on 400: Bad request
4357
+ #
4358
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
4359
+ # constructed with.
4360
+ # @param kind [String, nil] Restrict to one detector. Omitted returns all three, interleaved
4361
+ # by time.
4362
+ # @param limit [Integer, nil] Rows to return, newest first. Defaults to 50.
4363
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
4364
+ # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
4365
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
4366
+ def efficiency_alerts(org_id: nil, kind: nil, limit: nil, request_options: nil)
4367
+ @transport.request(
4368
+ http_method: "GET",
4369
+ path: "/api/org/{orgId}/costs/efficiency-alerts",
4370
+ path_params: { "orgId" => org_id },
4371
+ query: { "kind" => kind, "limit" => limit },
4372
+ request_options: request_options
4373
+ )
4374
+ end
4375
+
3516
4376
  # Query aggregated cost series
3517
4377
  #
3518
4378
  # Aggregates collected provider spend into per-bucket, per-group series for
@@ -3596,6 +4456,14 @@ module Infrawrench
3596
4456
  # centre and currency. Spend no rule claims comes back as the "Unallocated"
3597
4457
  # bucket; every defined centre appears even with zero spend.
3598
4458
  #
4459
+ # Cost centres nest, so the list is a depth-first tree. Each entry carries
4460
+ # `totals` (spend allocated directly to it) and `subtreeTotals` (its own
4461
+ # plus every descendant's) — "Engineering, of which Platform" needs both.
4462
+ # Rules still evaluate first-match-wins by ascending priority against a flat
4463
+ # list, so a row is allocated exactly once even when a rule targets a parent
4464
+ # and another targets its child; at equal priority the more deeply nested
4465
+ # centre wins.
4466
+ #
3599
4467
  # _Requires permission: `costs:read`._
3600
4468
  #
3601
4469
  # GET /api/org/{orgId}/costs/showback
@@ -3610,15 +4478,21 @@ module Infrawrench
3610
4478
  # charged on the day it charged it; `amortized` spreads a commitment's up-front fee across
3611
4479
  # the term it buys. Providers that report no amortized amount fall back to their cash
3612
4480
  # amount.
4481
+ # @param adjusted [String, nil] Apply the organization's billing rules (see /billing-rules):
4482
+ # markups multiply, and a reallocation moves a centre's spend onto another centre. Off by
4483
+ # default — a chargeback report that silently showed marked-up numbers is one the receiving
4484
+ # team could not reconcile. On, the response carries `adjustment` with the collected totals
4485
+ # beside the adjusted ones. Fixed-amount rules are booked onto the cost centre they name (or
4486
+ # "Unallocated" when they name none), pro-rated across the period.
3613
4487
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
3614
4488
  # @return [Hash] Parsed JSON, shaped as `ShowbackReport` — see `sig/infrawrench/sdk.rbs`.
3615
4489
  # @raise [Infrawrench::ApiError] On any non-2xx response.
3616
- def showback(org_id: nil, from: nil, to: nil, basis: nil, request_options: nil)
4490
+ def showback(org_id: nil, from: nil, to: nil, basis: nil, adjusted: nil, request_options: nil)
3617
4491
  @transport.request(
3618
4492
  http_method: "GET",
3619
4493
  path: "/api/org/{orgId}/costs/showback",
3620
4494
  path_params: { "orgId" => org_id },
3621
- query: { "from" => from, "to" => to, "basis" => basis },
4495
+ query: { "from" => from, "to" => to, "basis" => basis, "adjusted" => adjusted },
3622
4496
  request_options: request_options
3623
4497
  )
3624
4498
  end
@@ -5327,160 +6201,475 @@ module Infrawrench
5327
6201
  @transport = transport
5328
6202
  end
5329
6203
 
5330
- # Get the organization's expiry alert settings
6204
+ # Get the organization's expiry alert settings
6205
+ #
6206
+ # The lead time feeds both the feed's `upcoming` bucket and the poller's
6207
+ # daily alert scan. An organization that never saved reads the shipped
6208
+ # defaults (enabled, 60 days).
6209
+ #
6210
+ # _Requires permission: `org:settings:write`._
6211
+ #
6212
+ # GET /api/org/{orgId}/expiring/settings
6213
+ #
6214
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6215
+ # constructed with.
6216
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6217
+ # @return [Hash] Parsed JSON, shaped as `ExpiryAlertSettings` — see
6218
+ # `sig/infrawrench/sdk.rbs`.
6219
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6220
+ def get(org_id: nil, request_options: nil)
6221
+ @transport.request(
6222
+ http_method: "GET",
6223
+ path: "/api/org/{orgId}/expiring/settings",
6224
+ path_params: { "orgId" => org_id },
6225
+ request_options: request_options
6226
+ )
6227
+ end
6228
+
6229
+ # Update the expiry alert settings
6230
+ #
6231
+ # Every field is optional so a single toggle can be saved on its own.
6232
+ # `leadDays` must be a whole number from 1 to 365. Saving never resets the
6233
+ # alert cooldown.
6234
+ #
6235
+ # _Requires permission: `org:settings:write`._
6236
+ #
6237
+ # PUT /api/org/{orgId}/expiring/settings
6238
+ #
6239
+ # Raises on 400: Bad request
6240
+ #
6241
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6242
+ # constructed with.
6243
+ # @param body [Hash, nil] Request body, shaped as `ExpiryAlertSettingsUpdate`.
6244
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6245
+ # @return [Hash] Parsed JSON, shaped as `ExpiryAlertSettings` — see
6246
+ # `sig/infrawrench/sdk.rbs`.
6247
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6248
+ def update(org_id: nil, body: nil, request_options: nil)
6249
+ @transport.request(
6250
+ http_method: "PUT",
6251
+ path: "/api/org/{orgId}/expiring/settings",
6252
+ path_params: { "orgId" => org_id },
6253
+ body: body,
6254
+ request_options: request_options
6255
+ )
6256
+ end
6257
+ end
6258
+
6259
+ # `client.expiring`
6260
+ class ExpiringNamespace
6261
+ # @return [ExpiringSettingsNamespace] `client.expiring.settings`
6262
+ attr_reader :settings
6263
+
6264
+ # @api private
6265
+ # @param transport [Transport]
6266
+ def initialize(transport)
6267
+ @transport = transport
6268
+ @settings = ExpiringSettingsNamespace.new(@transport)
6269
+ end
6270
+
6271
+ # List approaching deadlines on synced resources
6272
+ #
6273
+ # One cross-provider countdown of everything with a clock on it: TLS
6274
+ # certificate expiries, domain registrations, API token expirations, access
6275
+ # keys past their rotation budget, Kubernetes/SSH credential ages. Plugins
6276
+ # declare which synced fields carry deadlines; the feed is computed over
6277
+ # already-stored state, so no provider API calls are made and results
6278
+ # reflect the last sync. Items are sorted soonest first and bucketed by
6279
+ # severity against the organization's lead time.
6280
+ #
6281
+ # _Requires permission: `resources:read`._
6282
+ #
6283
+ # GET /api/org/{orgId}/expiring
6284
+ #
6285
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6286
+ # constructed with.
6287
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6288
+ # @return [Hash] Parsed JSON, shaped as `ExpiryListResponse` — see
6289
+ # `sig/infrawrench/sdk.rbs`.
6290
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6291
+ def get(org_id: nil, request_options: nil)
6292
+ @transport.request(
6293
+ http_method: "GET",
6294
+ path: "/api/org/{orgId}/expiring",
6295
+ path_params: { "orgId" => org_id },
6296
+ request_options: request_options
6297
+ )
6298
+ end
6299
+ end
6300
+
6301
+ # `client.invitations.by_token`
6302
+ class InvitationsByTokenNamespace
6303
+ # @api private
6304
+ # @param transport [Transport]
6305
+ def initialize(transport)
6306
+ @transport = transport
6307
+ end
6308
+
6309
+ # Get invitation details by token
6310
+ #
6311
+ # GET /api/invitations/by-token/{token}
6312
+ #
6313
+ # Raises on 404: Not found
6314
+ #
6315
+ # @param token [String]
6316
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6317
+ # @return [Hash] Parsed JSON, shaped as `InvitationDetail` — see `sig/infrawrench/sdk.rbs`.
6318
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6319
+ def get(token:, request_options: nil)
6320
+ @transport.request(
6321
+ http_method: "GET",
6322
+ path: "/api/invitations/by-token/{token}",
6323
+ path_params: { "token" => token },
6324
+ request_options: request_options
6325
+ )
6326
+ end
6327
+ end
6328
+
6329
+ # `client.invitations`
6330
+ class InvitationsNamespace
6331
+ # @return [InvitationsByTokenNamespace] `client.invitations.by_token`
6332
+ attr_reader :by_token
6333
+
6334
+ # @api private
6335
+ # @param transport [Transport]
6336
+ def initialize(transport)
6337
+ @transport = transport
6338
+ @by_token = InvitationsByTokenNamespace.new(@transport)
6339
+ end
6340
+
6341
+ # Accept an invitation
6342
+ #
6343
+ # POST /api/invitations/accept
6344
+ #
6345
+ # Raises on 400: Bad request
6346
+ #
6347
+ # Raises on 403: Forbidden
6348
+ #
6349
+ # @param body [Hash] Request body, shaped as `AcceptInvitationRequest`.
6350
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6351
+ # @return [Hash] Parsed JSON, shaped as `AcceptInvitationResponse` — see
6352
+ # `sig/infrawrench/sdk.rbs`.
6353
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6354
+ def accept(body:, request_options: nil)
6355
+ @transport.request(
6356
+ http_method: "POST",
6357
+ path: "/api/invitations/accept",
6358
+ body: body,
6359
+ request_options: request_options
6360
+ )
6361
+ end
6362
+ end
6363
+
6364
+ # `client.invoices`
6365
+ class InvoicesNamespace
6366
+ # @api private
6367
+ # @param transport [Transport]
6368
+ def initialize(transport)
6369
+ @transport = transport
6370
+ end
6371
+
6372
+ # Approve an invoice — freeze its figures
6373
+ #
6374
+ # Computes the figures one last time and writes them onto the invoice
6375
+ # together with the exchange rates, the day they were read, the billing
6376
+ # rules in force and the names everything in scope had. From here the
6377
+ # invoice is a document, not a query.
6378
+ #
6379
+ # A distinct act from generation, on a distinct permission
6380
+ # (`invoices:issue`), with its own audit entry recording who approved what.
6381
+ #
6382
+ # Refused with 409 when a currency in the invoice has no stated exchange
6383
+ # rate: an approved invoice has to be quotable as one number in the
6384
+ # customer's currency.
6385
+ #
6386
+ # Refused with 409, too, when the draft or its customer changed while the
6387
+ # figures were being computed — a different period, scope, currency, cost
6388
+ # basis or billing-rules setting. Nothing is approved in that case: freezing
6389
+ # figures that describe a different question would be worse than making the
6390
+ # caller look again.
6391
+ #
6392
+ # _Requires permission: `invoices:issue`._
6393
+ #
6394
+ # POST /api/org/{orgId}/invoices/{id}/approve
6395
+ #
6396
+ # Raises on 404: Not found
6397
+ #
6398
+ # Raises on 409: Conflict
6399
+ #
6400
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6401
+ # constructed with.
6402
+ # @param id [String]
6403
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6404
+ # @return [Hash] Parsed JSON, shaped as `Invoice` — see `sig/infrawrench/sdk.rbs`.
6405
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6406
+ def approve(id:, org_id: nil, request_options: nil)
6407
+ @transport.request(
6408
+ http_method: "POST",
6409
+ path: "/api/org/{orgId}/invoices/{id}/approve",
6410
+ path_params: { "orgId" => org_id, "id" => id },
6411
+ request_options: request_options
6412
+ )
6413
+ end
6414
+
6415
+ # Raise a draft invoice
6416
+ #
6417
+ # Always lands in `draft`. Generating and issuing are two acts on two
6418
+ # permissions: a mistyped period must not be able to reach a customer
6419
+ # without anyone having read the numbers.
6420
+ #
6421
+ # _Requires permission: `invoices:write`._
6422
+ #
6423
+ # POST /api/org/{orgId}/invoices
6424
+ #
6425
+ # Raises on 400: Bad request
6426
+ #
6427
+ # Raises on 404: Not found
6428
+ #
6429
+ # Raises on 409: Conflict
6430
+ #
6431
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6432
+ # constructed with.
6433
+ # @param body [Hash] Request body, shaped as `InvoiceInput`.
6434
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6435
+ # @return [Hash] Parsed JSON, shaped as `Invoice` — see `sig/infrawrench/sdk.rbs`.
6436
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6437
+ def create(body:, org_id: nil, request_options: nil)
6438
+ @transport.request(
6439
+ http_method: "POST",
6440
+ path: "/api/org/{orgId}/invoices",
6441
+ path_params: { "orgId" => org_id },
6442
+ body: body,
6443
+ request_options: request_options
6444
+ )
6445
+ end
6446
+
6447
+ # Delete a draft invoice
6448
+ #
6449
+ # Draft only, and refused with 409 otherwise. An issued invoice is voided;
6450
+ # deleting one would erase a document a customer holds a copy of.
6451
+ #
6452
+ # _Requires permission: `invoices:write`._
6453
+ #
6454
+ # DELETE /api/org/{orgId}/invoices/{id}
6455
+ #
6456
+ # Raises on 404: Not found
6457
+ #
6458
+ # Raises on 409: Conflict
6459
+ #
6460
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6461
+ # constructed with.
6462
+ # @param id [String]
6463
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6464
+ # @return [Hash] Parsed JSON, shaped as `Ok` — see `sig/infrawrench/sdk.rbs`.
6465
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6466
+ def delete(id:, org_id: nil, request_options: nil)
6467
+ @transport.request(
6468
+ http_method: "DELETE",
6469
+ path: "/api/org/{orgId}/invoices/{id}",
6470
+ path_params: { "orgId" => org_id, "id" => id },
6471
+ request_options: request_options
6472
+ )
6473
+ end
6474
+
6475
+ # Download an invoice as CSV
5331
6476
  #
5332
- # The lead time feeds both the feed's `upcoming` bucket and the poller's
5333
- # daily alert scan. An organization that never saved reads the shipped
5334
- # defaults (enabled, 60 days).
6477
+ # The derivation, not a rendered document: what was collected, what the
6478
+ # rules added, the rate and the day it was read, and the final figure —
6479
+ # every column an accounts-payable clerk needs to check the arithmetic. Same
6480
+ # RFC 4180 quoting as the scheduled cost exports.
5335
6481
  #
5336
- # _Requires permission: `org:settings:write`._
6482
+ # _Requires permission: `invoices:read`._
5337
6483
  #
5338
- # GET /api/org/{orgId}/expiring/settings
6484
+ # GET /api/org/{orgId}/invoices/{id}/export
6485
+ #
6486
+ # Raises on 404: Not found
5339
6487
  #
5340
6488
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
5341
6489
  # constructed with.
6490
+ # @param id [String]
5342
6491
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
5343
- # @return [Hash] Parsed JSON, shaped as `ExpiryAlertSettings` — see
5344
- # `sig/infrawrench/sdk.rbs`.
6492
+ # @return [String] Raw response bytes.
5345
6493
  # @raise [Infrawrench::ApiError] On any non-2xx response.
5346
- def get(org_id: nil, request_options: nil)
6494
+ def export(id:, org_id: nil, request_options: nil)
5347
6495
  @transport.request(
5348
6496
  http_method: "GET",
5349
- path: "/api/org/{orgId}/expiring/settings",
5350
- path_params: { "orgId" => org_id },
6497
+ path: "/api/org/{orgId}/invoices/{id}/export",
6498
+ path_params: { "orgId" => org_id, "id" => id },
6499
+ accept: :binary,
5351
6500
  request_options: request_options
5352
6501
  )
5353
6502
  end
5354
6503
 
5355
- # Update the expiry alert settings
6504
+ # Get an invoice
5356
6505
  #
5357
- # Every field is optional so a single toggle can be saved on its own.
5358
- # `leadDays` must be a whole number from 1 to 365. Saving never resets the
5359
- # alert cooldown.
6506
+ # **A draft recomputes from live spend; an approved, sent or void invoice
6507
+ # does not.** `live` says which happened. A frozen invoice returns the
6508
+ # figures written at approval and does not read cost data at all.
5360
6509
  #
5361
- # _Requires permission: `org:settings:write`._
6510
+ # _Requires permission: `invoices:read`._
5362
6511
  #
5363
- # PUT /api/org/{orgId}/expiring/settings
6512
+ # GET /api/org/{orgId}/invoices/{id}
5364
6513
  #
5365
- # Raises on 400: Bad request
6514
+ # Raises on 404: Not found
5366
6515
  #
5367
6516
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
5368
6517
  # constructed with.
5369
- # @param body [Hash, nil] Request body, shaped as `ExpiryAlertSettingsUpdate`.
6518
+ # @param id [String]
5370
6519
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
5371
- # @return [Hash] Parsed JSON, shaped as `ExpiryAlertSettings` — see
5372
- # `sig/infrawrench/sdk.rbs`.
6520
+ # @return [Hash] Parsed JSON, shaped as `Invoice` — see `sig/infrawrench/sdk.rbs`.
5373
6521
  # @raise [Infrawrench::ApiError] On any non-2xx response.
5374
- def update(org_id: nil, body: nil, request_options: nil)
6522
+ def get(id:, org_id: nil, request_options: nil)
5375
6523
  @transport.request(
5376
- http_method: "PUT",
5377
- path: "/api/org/{orgId}/expiring/settings",
5378
- path_params: { "orgId" => org_id },
5379
- body: body,
6524
+ http_method: "GET",
6525
+ path: "/api/org/{orgId}/invoices/{id}",
6526
+ path_params: { "orgId" => org_id, "id" => id },
5380
6527
  request_options: request_options
5381
6528
  )
5382
6529
  end
5383
- end
5384
-
5385
- # `client.expiring`
5386
- class ExpiringNamespace
5387
- # @return [ExpiringSettingsNamespace] `client.expiring.settings`
5388
- attr_reader :settings
5389
-
5390
- # @api private
5391
- # @param transport [Transport]
5392
- def initialize(transport)
5393
- @transport = transport
5394
- @settings = ExpiringSettingsNamespace.new(@transport)
5395
- end
5396
6530
 
5397
- # List approaching deadlines on synced resources
6531
+ # List invoices
5398
6532
  #
5399
- # One cross-provider countdown of everything with a clock on it: TLS
5400
- # certificate expiries, domain registrations, API token expirations, access
5401
- # keys past their rotation budget, Kubernetes/SSH credential ages. Plugins
5402
- # declare which synced fields carry deadlines; the feed is computed over
5403
- # already-stored state, so no provider API calls are made and results
5404
- # reflect the last sync. Items are sorted soonest first and bucketed by
5405
- # severity against the organization's lead time.
6533
+ # Summaries, newest period first. A draft's `totals` is null here rather
6534
+ # than recomputed — recomputing every draft would make opening the list one
6535
+ # cost-data scan per draft, and zero would be a lie the reader cannot
6536
+ # detect.
5406
6537
  #
5407
- # _Requires permission: `resources:read`._
6538
+ # _Requires permission: `invoices:read`._
5408
6539
  #
5409
- # GET /api/org/{orgId}/expiring
6540
+ # GET /api/org/{orgId}/invoices
6541
+ #
6542
+ # Raises on 400: Bad request
5410
6543
  #
5411
6544
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
5412
6545
  # constructed with.
6546
+ # @param managed_account_id [String, nil]
6547
+ # @param status [String, nil]
5413
6548
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
5414
- # @return [Hash] Parsed JSON, shaped as `ExpiryListResponse` — see
6549
+ # @return [Array<Hash>] Parsed JSON, shaped as `Array<InvoiceSummary>` — see
5415
6550
  # `sig/infrawrench/sdk.rbs`.
5416
6551
  # @raise [Infrawrench::ApiError] On any non-2xx response.
5417
- def get(org_id: nil, request_options: nil)
6552
+ def list(org_id: nil, managed_account_id: nil, status: nil, request_options: nil)
5418
6553
  @transport.request(
5419
6554
  http_method: "GET",
5420
- path: "/api/org/{orgId}/expiring",
6555
+ path: "/api/org/{orgId}/invoices",
5421
6556
  path_params: { "orgId" => org_id },
6557
+ query: { "managedAccountId" => managed_account_id, "status" => status },
5422
6558
  request_options: request_options
5423
6559
  )
5424
6560
  end
5425
- end
5426
-
5427
- # `client.invitations.by_token`
5428
- class InvitationsByTokenNamespace
5429
- # @api private
5430
- # @param transport [Transport]
5431
- def initialize(transport)
5432
- @transport = transport
5433
- end
5434
6561
 
5435
- # Get invitation details by token
6562
+ # Send an invoice to its customer
5436
6563
  #
5437
- # GET /api/invitations/by-token/{token}
6564
+ # Changes no figure — the document was frozen at approval. It records the
6565
+ # **release** (this may go to the customer, and this person said so), then
6566
+ # emails the invoice to the customer's contact addresses with the CSV
6567
+ # attached.
6568
+ #
6569
+ # **200 even when delivery failed.** The release happened and is recorded
6570
+ # either way; `delivery` says what became of the transport. An error status
6571
+ # would leave the caller unable to tell which of the two failed. A failed
6572
+ # delivery is visible, and re-sending retries it.
6573
+ #
6574
+ # Sending again needs `resend: true` only when the last attempt reached
6575
+ # somebody — see `InvoiceSendRequest`. The body may be omitted entirely for
6576
+ # a first send.
6577
+ #
6578
+ # _Requires permission: `invoices:issue`._
6579
+ #
6580
+ # POST /api/org/{orgId}/invoices/{id}/send
6581
+ #
6582
+ # Raises on 400: Bad request
5438
6583
  #
5439
6584
  # Raises on 404: Not found
5440
6585
  #
5441
- # @param token [String]
6586
+ # Raises on 409: Conflict
6587
+ #
6588
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6589
+ # constructed with.
6590
+ # @param id [String]
6591
+ # @param body [Hash, nil] Request body, shaped as `InvoiceSendRequest`.
5442
6592
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
5443
- # @return [Hash] Parsed JSON, shaped as `InvitationDetail` — see `sig/infrawrench/sdk.rbs`.
6593
+ # @return [Hash] Parsed JSON, shaped as `Invoice` — see `sig/infrawrench/sdk.rbs`.
5444
6594
  # @raise [Infrawrench::ApiError] On any non-2xx response.
5445
- def get(token:, request_options: nil)
6595
+ def post_org_org_id_invoices_id_send(id:, org_id: nil, body: nil, request_options: nil)
5446
6596
  @transport.request(
5447
- http_method: "GET",
5448
- path: "/api/invitations/by-token/{token}",
5449
- path_params: { "token" => token },
6597
+ http_method: "POST",
6598
+ path: "/api/org/{orgId}/invoices/{id}/send",
6599
+ path_params: { "orgId" => org_id, "id" => id },
6600
+ body: body,
5450
6601
  request_options: request_options
5451
6602
  )
5452
6603
  end
5453
- end
5454
-
5455
- # `client.invitations`
5456
- class InvitationsNamespace
5457
- # @return [InvitationsByTokenNamespace] `client.invitations.by_token`
5458
- attr_reader :by_token
5459
6604
 
5460
- # @api private
5461
- # @param transport [Transport]
5462
- def initialize(transport)
5463
- @transport = transport
5464
- @by_token = InvitationsByTokenNamespace.new(@transport)
6605
+ # Edit a draft invoice
6606
+ #
6607
+ # Draft only. An approved, sent or void invoice is refused with 409 by the
6608
+ # service, not merely hidden by the UI — an issued invoice that silently
6609
+ # changed after the customer received it is the worst outcome this feature
6610
+ # could produce.
6611
+ #
6612
+ # _Requires permission: `invoices:write`._
6613
+ #
6614
+ # PUT /api/org/{orgId}/invoices/{id}
6615
+ #
6616
+ # Raises on 400: Bad request
6617
+ #
6618
+ # Raises on 404: Not found
6619
+ #
6620
+ # Raises on 409: Conflict
6621
+ #
6622
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6623
+ # constructed with.
6624
+ # @param id [String]
6625
+ # @param body [Hash] Request body, shaped as `InvoiceUpdate`.
6626
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6627
+ # @return [Hash] Parsed JSON, shaped as `Invoice` — see `sig/infrawrench/sdk.rbs`.
6628
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6629
+ def update(id:, body:, org_id: nil, request_options: nil)
6630
+ @transport.request(
6631
+ http_method: "PUT",
6632
+ path: "/api/org/{orgId}/invoices/{id}",
6633
+ path_params: { "orgId" => org_id, "id" => id },
6634
+ body: body,
6635
+ request_options: request_options
6636
+ )
5465
6637
  end
5466
6638
 
5467
- # Accept an invitation
6639
+ # Void an issued invoice
5468
6640
  #
5469
- # POST /api/invitations/accept
6641
+ # The only correction there is. The original keeps every figure it was sent
6642
+ # with — “we billed you this, it was wrong, here is the corrected one” is a
6643
+ # story a customer can follow, and “we changed the invoice” is not.
6644
+ #
6645
+ # With `supersede`, the void, the corrective draft and both directions of
6646
+ # the link between them are one transaction. Void is irreversible, so a
6647
+ # half-applied correction would leave a withdrawn invoice with no way
6648
+ # forward; this call either applies whole or not at all.
6649
+ #
6650
+ # _Requires permission: `invoices:issue`._
6651
+ #
6652
+ # POST /api/org/{orgId}/invoices/{id}/void
5470
6653
  #
5471
6654
  # Raises on 400: Bad request
5472
6655
  #
5473
- # Raises on 403: Forbidden
6656
+ # Raises on 404: Not found
5474
6657
  #
5475
- # @param body [Hash] Request body, shaped as `AcceptInvitationRequest`.
6658
+ # Raises on 409: Conflict
6659
+ #
6660
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6661
+ # constructed with.
6662
+ # @param id [String]
6663
+ # @param body [Hash] Request body, shaped as `InvoiceVoidRequest`.
5476
6664
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
5477
- # @return [Hash] Parsed JSON, shaped as `AcceptInvitationResponse` — see
6665
+ # @return [Hash] Parsed JSON, shaped as `InvoiceVoidResponse` — see
5478
6666
  # `sig/infrawrench/sdk.rbs`.
5479
6667
  # @raise [Infrawrench::ApiError] On any non-2xx response.
5480
- def accept(body:, request_options: nil)
6668
+ def void(id:, body:, org_id: nil, request_options: nil)
5481
6669
  @transport.request(
5482
6670
  http_method: "POST",
5483
- path: "/api/invitations/accept",
6671
+ path: "/api/org/{orgId}/invoices/{id}/void",
6672
+ path_params: { "orgId" => org_id, "id" => id },
5484
6673
  body: body,
5485
6674
  request_options: request_options
5486
6675
  )
@@ -6293,6 +7482,156 @@ module Infrawrench
6293
7482
  end
6294
7483
  end
6295
7484
 
7485
+ # `client.managed_accounts`
7486
+ class ManagedAccountsNamespace
7487
+ # @api private
7488
+ # @param transport [Transport]
7489
+ def initialize(transport)
7490
+ @transport = transport
7491
+ end
7492
+
7493
+ # Create a managed account
7494
+ #
7495
+ # Refused with 409 when a cost centre or account named here is already
7496
+ # billed to another customer. The error names the other customer, because
7497
+ # “it conflicts” without saying with whom sends the caller hunting.
7498
+ #
7499
+ # _Requires permission: `invoices:write`._
7500
+ #
7501
+ # POST /api/org/{orgId}/managed-accounts
7502
+ #
7503
+ # Raises on 400: Bad request
7504
+ #
7505
+ # Raises on 409: Conflict
7506
+ #
7507
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7508
+ # constructed with.
7509
+ # @param body [Hash] Request body, shaped as `ManagedAccountInput`.
7510
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7511
+ # @return [Hash] Parsed JSON, shaped as `ManagedAccount` — see `sig/infrawrench/sdk.rbs`.
7512
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7513
+ def create(body:, org_id: nil, request_options: nil)
7514
+ @transport.request(
7515
+ http_method: "POST",
7516
+ path: "/api/org/{orgId}/managed-accounts",
7517
+ path_params: { "orgId" => org_id },
7518
+ body: body,
7519
+ request_options: request_options
7520
+ )
7521
+ end
7522
+
7523
+ # Retire a managed account
7524
+ #
7525
+ # A soft delete: an issued invoice names its customer, and an invoice whose
7526
+ # customer stopped resolving is exactly the unreconcilable document this
7527
+ # feature exists to prevent. Draft invoices are removed with it — a draft
7528
+ # was never issued.
7529
+ #
7530
+ # _Requires permission: `invoices:write`._
7531
+ #
7532
+ # DELETE /api/org/{orgId}/managed-accounts/{id}
7533
+ #
7534
+ # Raises on 404: Not found
7535
+ #
7536
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7537
+ # constructed with.
7538
+ # @param id [String]
7539
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7540
+ # @return [Hash] Parsed JSON, shaped as `Ok` — see `sig/infrawrench/sdk.rbs`.
7541
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7542
+ def delete(id:, org_id: nil, request_options: nil)
7543
+ @transport.request(
7544
+ http_method: "DELETE",
7545
+ path: "/api/org/{orgId}/managed-accounts/{id}",
7546
+ path_params: { "orgId" => org_id, "id" => id },
7547
+ request_options: request_options
7548
+ )
7549
+ end
7550
+
7551
+ # Get a managed account
7552
+ #
7553
+ # _Requires permission: `invoices:read`._
7554
+ #
7555
+ # GET /api/org/{orgId}/managed-accounts/{id}
7556
+ #
7557
+ # Raises on 404: Not found
7558
+ #
7559
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7560
+ # constructed with.
7561
+ # @param id [String]
7562
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7563
+ # @return [Hash] Parsed JSON, shaped as `ManagedAccount` — see `sig/infrawrench/sdk.rbs`.
7564
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7565
+ def get(id:, org_id: nil, request_options: nil)
7566
+ @transport.request(
7567
+ http_method: "GET",
7568
+ path: "/api/org/{orgId}/managed-accounts/{id}",
7569
+ path_params: { "orgId" => org_id, "id" => id },
7570
+ request_options: request_options
7571
+ )
7572
+ end
7573
+
7574
+ # List managed accounts
7575
+ #
7576
+ # The customers a managed service provider bills. A managed account
7577
+ # references existing cost centres rather than defining its own matching
7578
+ # rules, so the spend on an invoice is the same spend the showback report
7579
+ # attributes to those centres.
7580
+ #
7581
+ # _Requires permission: `invoices:read`._
7582
+ #
7583
+ # GET /api/org/{orgId}/managed-accounts
7584
+ #
7585
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7586
+ # constructed with.
7587
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7588
+ # @return [Array<Hash>] Parsed JSON, shaped as `Array<ManagedAccount>` — see
7589
+ # `sig/infrawrench/sdk.rbs`.
7590
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7591
+ def list(org_id: nil, request_options: nil)
7592
+ @transport.request(
7593
+ http_method: "GET",
7594
+ path: "/api/org/{orgId}/managed-accounts",
7595
+ path_params: { "orgId" => org_id },
7596
+ request_options: request_options
7597
+ )
7598
+ end
7599
+
7600
+ # Update a managed account
7601
+ #
7602
+ # A full replace. Editing the scope changes what **future** drafts are drawn
7603
+ # over and nothing else: every approved invoice holds its own copy of the
7604
+ # scope, so moving a cost centre between customers cannot re-bill a period
7605
+ # that has already been invoiced.
7606
+ #
7607
+ # _Requires permission: `invoices:write`._
7608
+ #
7609
+ # PUT /api/org/{orgId}/managed-accounts/{id}
7610
+ #
7611
+ # Raises on 400: Bad request
7612
+ #
7613
+ # Raises on 404: Not found
7614
+ #
7615
+ # Raises on 409: Conflict
7616
+ #
7617
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7618
+ # constructed with.
7619
+ # @param id [String]
7620
+ # @param body [Hash] Request body, shaped as `ManagedAccountInput`.
7621
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7622
+ # @return [Hash] Parsed JSON, shaped as `ManagedAccount` — see `sig/infrawrench/sdk.rbs`.
7623
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7624
+ def update(id:, body:, org_id: nil, request_options: nil)
7625
+ @transport.request(
7626
+ http_method: "PUT",
7627
+ path: "/api/org/{orgId}/managed-accounts/{id}",
7628
+ path_params: { "orgId" => org_id, "id" => id },
7629
+ body: body,
7630
+ request_options: request_options
7631
+ )
7632
+ end
7633
+ end
7634
+
6296
7635
  # `client.metric_alerts`
6297
7636
  class MetricAlertsNamespace
6298
7637
  # @api private
@@ -11137,8 +12476,12 @@ module Infrawrench
11137
12476
  attr_reader :bastions
11138
12477
  # @return [BillingNamespace] `client.billing`
11139
12478
  attr_reader :billing
12479
+ # @return [BillingRulesNamespace] `client.billing_rules`
12480
+ attr_reader :billing_rules
11140
12481
  # @return [BudgetsNamespace] `client.budgets`
11141
12482
  attr_reader :budgets
12483
+ # @return [BusinessMetricsNamespace] `client.business_metrics`
12484
+ attr_reader :business_metrics
11142
12485
  # @return [ChangeFreezesNamespace] `client.change_freezes`
11143
12486
  attr_reader :change_freezes
11144
12487
  # @return [ChangesNamespace] `client.changes`
@@ -11151,6 +12494,8 @@ module Infrawrench
11151
12494
  attr_reader :connect
11152
12495
  # @return [CostAlertsNamespace] `client.cost_alerts`
11153
12496
  attr_reader :cost_alerts
12497
+ # @return [CostAnnotationsNamespace] `client.cost_annotations`
12498
+ attr_reader :cost_annotations
11154
12499
  # @return [CostCentresNamespace] `client.cost_centres`
11155
12500
  attr_reader :cost_centres
11156
12501
  # @return [CostExportsNamespace] `client.cost_exports`
@@ -11161,6 +12506,8 @@ module Infrawrench
11161
12506
  attr_reader :cost_report_notifications
11162
12507
  # @return [CostReportsNamespace] `client.cost_reports`
11163
12508
  attr_reader :cost_reports
12509
+ # @return [CostScenariosNamespace] `client.cost_scenarios`
12510
+ attr_reader :cost_scenarios
11164
12511
  # @return [CostsNamespace] `client.costs`
11165
12512
  attr_reader :costs
11166
12513
  # @return [CredentialHygieneNamespace] `client.credential_hygiene`
@@ -11189,6 +12536,8 @@ module Infrawrench
11189
12536
  attr_reader :expiring
11190
12537
  # @return [InvitationsNamespace] `client.invitations`
11191
12538
  attr_reader :invitations
12539
+ # @return [InvoicesNamespace] `client.invoices`
12540
+ attr_reader :invoices
11192
12541
  # @return [JiraNamespace] `client.jira`
11193
12542
  attr_reader :jira
11194
12543
  # @return [KvNamespace] `client.kv`
@@ -11199,6 +12548,8 @@ module Infrawrench
11199
12548
  attr_reader :linear
11200
12549
  # @return [LogWorkspacesNamespace] `client.log_workspaces`
11201
12550
  attr_reader :log_workspaces
12551
+ # @return [ManagedAccountsNamespace] `client.managed_accounts`
12552
+ attr_reader :managed_accounts
11202
12553
  # @return [MetricAlertsNamespace] `client.metric_alerts`
11203
12554
  attr_reader :metric_alerts
11204
12555
  # @return [MomentNamespace] `client.moment`
@@ -11276,18 +12627,22 @@ module Infrawrench
11276
12627
  @auth = AuthNamespace.new(@transport)
11277
12628
  @bastions = BastionsNamespace.new(@transport)
11278
12629
  @billing = BillingNamespace.new(@transport)
12630
+ @billing_rules = BillingRulesNamespace.new(@transport)
11279
12631
  @budgets = BudgetsNamespace.new(@transport)
12632
+ @business_metrics = BusinessMetricsNamespace.new(@transport)
11280
12633
  @change_freezes = ChangeFreezesNamespace.new(@transport)
11281
12634
  @changes = ChangesNamespace.new(@transport)
11282
12635
  @commitments = CommitmentsNamespace.new(@transport)
11283
12636
  @config = ConfigNamespace.new(@transport)
11284
12637
  @connect = ConnectNamespace.new(@transport)
11285
12638
  @cost_alerts = CostAlertsNamespace.new(@transport)
12639
+ @cost_annotations = CostAnnotationsNamespace.new(@transport)
11286
12640
  @cost_centres = CostCentresNamespace.new(@transport)
11287
12641
  @cost_exports = CostExportsNamespace.new(@transport)
11288
12642
  @cost_report_folders = CostReportFoldersNamespace.new(@transport)
11289
12643
  @cost_report_notifications = CostReportNotificationsNamespace.new(@transport)
11290
12644
  @cost_reports = CostReportsNamespace.new(@transport)
12645
+ @cost_scenarios = CostScenariosNamespace.new(@transport)
11291
12646
  @costs = CostsNamespace.new(@transport)
11292
12647
  @credential_hygiene = CredentialHygieneNamespace.new(@transport)
11293
12648
  @credits = CreditsNamespace.new(@transport)
@@ -11302,11 +12657,13 @@ module Infrawrench
11302
12657
  @environment_diff = EnvironmentDiffNamespace.new(@transport)
11303
12658
  @expiring = ExpiringNamespace.new(@transport)
11304
12659
  @invitations = InvitationsNamespace.new(@transport)
12660
+ @invoices = InvoicesNamespace.new(@transport)
11305
12661
  @jira = JiraNamespace.new(@transport)
11306
12662
  @kv = KvNamespace.new(@transport)
11307
12663
  @leases = LeasesNamespace.new(@transport)
11308
12664
  @linear = LinearNamespace.new(@transport)
11309
12665
  @log_workspaces = LogWorkspacesNamespace.new(@transport)
12666
+ @managed_accounts = ManagedAccountsNamespace.new(@transport)
11310
12667
  @metric_alerts = MetricAlertsNamespace.new(@transport)
11311
12668
  @moment = MomentNamespace.new(@transport)
11312
12669
  @msteams = MsteamsNamespace.new(@transport)