overturo 0.7.2
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.
- checksums.yaml +7 -0
- data/LICENSE +201 -0
- data/README.md +395 -0
- data/lib/overturo/api_operations/create.rb +14 -0
- data/lib/overturo/api_operations/delete.rb +14 -0
- data/lib/overturo/api_operations/list.rb +14 -0
- data/lib/overturo/api_operations/nested_resource.rb +52 -0
- data/lib/overturo/api_operations/retrieve.rb +14 -0
- data/lib/overturo/api_operations/update.rb +14 -0
- data/lib/overturo/api_resource.rb +107 -0
- data/lib/overturo/client.rb +231 -0
- data/lib/overturo/configuration.rb +24 -0
- data/lib/overturo/endpoints.rb +27 -0
- data/lib/overturo/errors.rb +120 -0
- data/lib/overturo/http_client.rb +166 -0
- data/lib/overturo/list_object.rb +73 -0
- data/lib/overturo/overturo_object.rb +87 -0
- data/lib/overturo/resources/agree/agreements.rb +20 -0
- data/lib/overturo/resources/agree/collaborations.rb +20 -0
- data/lib/overturo/resources/agree/quorum_requests.rb +22 -0
- data/lib/overturo/resources/comply/anchors.rb +25 -0
- data/lib/overturo/resources/comply/clean_rooms.rb +46 -0
- data/lib/overturo/resources/comply/evidence_packages.rb +15 -0
- data/lib/overturo/resources/comply/residency_posture.rb +31 -0
- data/lib/overturo/resources/comply/transfer_register.rb +28 -0
- data/lib/overturo/resources/connect/applications.rb +20 -0
- data/lib/overturo/resources/connect/connections.rb +20 -0
- data/lib/overturo/resources/connect/flows.rb +77 -0
- data/lib/overturo/resources/connect/meeting_consents.rb +60 -0
- data/lib/overturo/resources/connect/portability.rb +45 -0
- data/lib/overturo/resources/connect/webhooks.rb +42 -0
- data/lib/overturo/resources/consent/consent_records.rb +57 -0
- data/lib/overturo/resources/consent/consent_sessions.rb +49 -0
- data/lib/overturo/resources/consent/decisions.rb +54 -0
- data/lib/overturo/resources/consent/entitlements.rb +18 -0
- data/lib/overturo/resources/consent/trust_levels.rb +18 -0
- data/lib/overturo/resources/core/accounts.rb +18 -0
- data/lib/overturo/resources/core/me.rb +20 -0
- data/lib/overturo/resources/delegate/agent_identities.rb +23 -0
- data/lib/overturo/resources/delegate/authorization_receipts.rb +38 -0
- data/lib/overturo/resources/delegate/delegations.rb +34 -0
- data/lib/overturo/resources/delegate/disclosure_receipts.rb +24 -0
- data/lib/overturo/resources/delegate/security_event_streams.rb +22 -0
- data/lib/overturo/resources/protect/data_licenses.rb +19 -0
- data/lib/overturo/resources/protect/data_requests.rb +17 -0
- data/lib/overturo/resources/protect/policies.rb +23 -0
- data/lib/overturo/resources/protect/transfers.rb +19 -0
- data/lib/overturo/resources/verify/credentials.rb +23 -0
- data/lib/overturo/resources/verify/presentations.rb +18 -0
- data/lib/overturo/resources/verify/trust_scores.rb +17 -0
- data/lib/overturo/resources/verify/verification_sessions.rb +16 -0
- data/lib/overturo/resources/verify/vouches.rb +29 -0
- data/lib/overturo/version.rb +5 -0
- data/lib/overturo.rb +85 -0
- metadata +99 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "uri"
|
|
5
|
+
require "json"
|
|
6
|
+
require "securerandom"
|
|
7
|
+
|
|
8
|
+
module Overturo
|
|
9
|
+
class HttpClient
|
|
10
|
+
RETRY_SLEEP_BASE = 0.5
|
|
11
|
+
|
|
12
|
+
attr_reader :last_request_id
|
|
13
|
+
|
|
14
|
+
def initialize(config)
|
|
15
|
+
@config = config
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def get(path, params: {}, headers: {})
|
|
19
|
+
request(:get, path, params: params, extra_request_headers: headers)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def post(path, body: {}, idempotency_key: nil)
|
|
23
|
+
request(:post, path, body: body, idempotency_key: idempotency_key)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def patch(path, body: {}, idempotency_key: nil)
|
|
27
|
+
request(:patch, path, body: body, idempotency_key: idempotency_key)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def delete(path)
|
|
31
|
+
request(:delete, path)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def request(method, path, params: {}, body: nil, idempotency_key: nil, extra_request_headers: {})
|
|
37
|
+
uri = build_uri(path, params)
|
|
38
|
+
request_id = generate_request_id
|
|
39
|
+
retries = 0
|
|
40
|
+
|
|
41
|
+
begin
|
|
42
|
+
response = execute_request(method, uri, body, request_id: request_id, idempotency_key: idempotency_key,
|
|
43
|
+
extra_request_headers: extra_request_headers)
|
|
44
|
+
handle_response(response)
|
|
45
|
+
rescue RateLimitError, ApiError, ConnectionError, TimeoutError => e
|
|
46
|
+
if retries < @config.max_retries && retryable?(e)
|
|
47
|
+
retries += 1
|
|
48
|
+
sleep_time = RETRY_SLEEP_BASE * (2**(retries - 1))
|
|
49
|
+
log(:warn, "Retrying request #{request_id} (attempt #{retries}/#{@config.max_retries}) after #{sleep_time}s")
|
|
50
|
+
sleep(sleep_time)
|
|
51
|
+
retry
|
|
52
|
+
end
|
|
53
|
+
raise
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def execute_request(method, uri, body, request_id: nil, idempotency_key: nil, extra_request_headers: {})
|
|
58
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
59
|
+
http.use_ssl = uri.scheme == "https"
|
|
60
|
+
http.open_timeout = @config.open_timeout
|
|
61
|
+
http.read_timeout = @config.read_timeout
|
|
62
|
+
http.write_timeout = @config.write_timeout
|
|
63
|
+
|
|
64
|
+
req = build_request(method, uri, body, request_id: request_id, idempotency_key: idempotency_key,
|
|
65
|
+
extra_request_headers: extra_request_headers)
|
|
66
|
+
log(:debug, "[#{request_id}] #{method.upcase} #{uri.path}")
|
|
67
|
+
http.request(req)
|
|
68
|
+
rescue ::Timeout::Error, Errno::ETIMEDOUT => e
|
|
69
|
+
raise Overturo::TimeoutError, "Request timed out: #{e.message}"
|
|
70
|
+
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EHOSTUNREACH,
|
|
71
|
+
Errno::ENETUNREACH, SocketError, EOFError => e
|
|
72
|
+
raise Overturo::ConnectionError, "Connection failed: #{e.message}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def build_request(method, uri, body, request_id: nil, idempotency_key: nil, extra_request_headers: {})
|
|
76
|
+
klass = {
|
|
77
|
+
get: Net::HTTP::Get,
|
|
78
|
+
post: Net::HTTP::Post,
|
|
79
|
+
patch: Net::HTTP::Patch,
|
|
80
|
+
delete: Net::HTTP::Delete
|
|
81
|
+
}.fetch(method)
|
|
82
|
+
|
|
83
|
+
extra_headers = {}
|
|
84
|
+
extra_headers["X-Request-ID"] = request_id if request_id
|
|
85
|
+
extra_headers["Idempotency-Key"] = idempotency_key if idempotency_key
|
|
86
|
+
# 189 — caller-supplied per-request headers (e.g. the discovery resource's
|
|
87
|
+
# X-Publishable-Key). Merged last so an explicit header wins.
|
|
88
|
+
extra_headers.merge!(extra_request_headers) if extra_request_headers && !extra_request_headers.empty?
|
|
89
|
+
|
|
90
|
+
req = klass.new(uri.request_uri, headers.merge(extra_headers))
|
|
91
|
+
req.body = JSON.generate(body) if body && !body.empty?
|
|
92
|
+
req
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build_uri(path, params)
|
|
96
|
+
# chomp a trailing slash so a base_url like "https://x.com/" doesn't produce
|
|
97
|
+
# "https://x.com//api/..." (some gateways 404 the double slash).
|
|
98
|
+
url = "#{@config.base_url.to_s.chomp("/")}/api/#{@config.api_version}#{path}"
|
|
99
|
+
uri = URI.parse(url)
|
|
100
|
+
uri.query = URI.encode_www_form(params) if params && !params.empty?
|
|
101
|
+
uri
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def headers
|
|
105
|
+
{
|
|
106
|
+
"Authorization" => "Bearer #{@config.api_key}",
|
|
107
|
+
"Content-Type" => "application/json",
|
|
108
|
+
"Accept" => "application/json",
|
|
109
|
+
"User-Agent" => "overturo-ruby/#{Overturo::VERSION}"
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def handle_response(response)
|
|
114
|
+
@last_response_request_id = response["X-Request-ID"]
|
|
115
|
+
status = response.code.to_i
|
|
116
|
+
body = response.body
|
|
117
|
+
json = parse_json(body)
|
|
118
|
+
|
|
119
|
+
return json || {} if status >= 200 && status < 300
|
|
120
|
+
|
|
121
|
+
message = error_message(json, body)
|
|
122
|
+
error_class = ERROR_MAP[status] || (status >= 500 ? ApiError : Error)
|
|
123
|
+
|
|
124
|
+
raise error_class.new(
|
|
125
|
+
message.to_s,
|
|
126
|
+
http_status: status,
|
|
127
|
+
http_body: body,
|
|
128
|
+
json_body: json
|
|
129
|
+
)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# `{error: {code, message}}` reads as "code: message"; a string error or a
|
|
133
|
+
# non-JSON body is passed through.
|
|
134
|
+
def error_message(json, body)
|
|
135
|
+
return body unless json.is_a?(Hash)
|
|
136
|
+
|
|
137
|
+
error = json["error"]
|
|
138
|
+
return [error["code"], error["message"]].compact.join(": ") if error.is_a?(Hash)
|
|
139
|
+
|
|
140
|
+
error || body
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def parse_json(body)
|
|
144
|
+
return nil if body.nil? || body.empty?
|
|
145
|
+
|
|
146
|
+
JSON.parse(body)
|
|
147
|
+
rescue JSON::ParserError
|
|
148
|
+
nil
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def retryable?(error)
|
|
152
|
+
error.is_a?(RateLimitError) || error.is_a?(ApiError) ||
|
|
153
|
+
error.is_a?(ConnectionError) || error.is_a?(TimeoutError)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def generate_request_id
|
|
157
|
+
@last_request_id = "req_#{SecureRandom.hex(12)}"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def log(level, message)
|
|
161
|
+
return unless @config.logger
|
|
162
|
+
|
|
163
|
+
@config.logger.send(level, "[Overturo] #{message}")
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
class ListObject
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
attr_reader :data, :pagination
|
|
8
|
+
|
|
9
|
+
def initialize(data:, pagination:, http_client: nil, resource_path: nil, list_key: nil, params: {})
|
|
10
|
+
@data = data
|
|
11
|
+
@pagination = pagination
|
|
12
|
+
@http_client = http_client
|
|
13
|
+
@resource_path = resource_path
|
|
14
|
+
@list_key = list_key
|
|
15
|
+
@params = params
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def each(&)
|
|
19
|
+
@data.each(&)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def more?
|
|
23
|
+
return false unless pagination
|
|
24
|
+
|
|
25
|
+
page_value(:page, 1) * page_value(:per_page, 25) < page_value(:total, 0)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
alias has_more? more?
|
|
29
|
+
|
|
30
|
+
def auto_paging_each(&block)
|
|
31
|
+
return enum_for(:auto_paging_each) unless block_given?
|
|
32
|
+
|
|
33
|
+
@data.each(&block)
|
|
34
|
+
return unless @http_client && @resource_path && @list_key
|
|
35
|
+
|
|
36
|
+
current_params = @params.dup
|
|
37
|
+
current_page = page_value(:page, 1)
|
|
38
|
+
|
|
39
|
+
while pages_remaining?(current_page)
|
|
40
|
+
current_page += 1
|
|
41
|
+
current_params[:page] = current_page
|
|
42
|
+
response = @http_client.get(@resource_path, params: current_params)
|
|
43
|
+
items = response[@list_key] || []
|
|
44
|
+
items.each do |item|
|
|
45
|
+
block.call(item.is_a?(OverturoObject) ? item : OverturoObject.new(item))
|
|
46
|
+
end
|
|
47
|
+
@pagination = response["pagination"] || {}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def empty?
|
|
52
|
+
@data.empty?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def size
|
|
56
|
+
@data.size
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
alias length size
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def page_value(key, default)
|
|
64
|
+
return default unless pagination
|
|
65
|
+
|
|
66
|
+
pagination[key.to_s] || pagination[key.to_sym] || default
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def pages_remaining?(current_page)
|
|
70
|
+
current_page * page_value(:per_page, 25) < page_value(:total, 0)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
class OverturoObject
|
|
5
|
+
def initialize(data = {})
|
|
6
|
+
@data = {}
|
|
7
|
+
data.each { |k, v| @data[k.to_s] = wrap_value(v) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def [](key)
|
|
11
|
+
@data[key.to_s]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def []=(key, value)
|
|
15
|
+
@data[key.to_s] = wrap_value(value)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
19
|
+
@data.key?(method_name.to_s) || super
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def method_missing(method_name, *args)
|
|
23
|
+
key = method_name.to_s
|
|
24
|
+
if @data.key?(key)
|
|
25
|
+
@data[key]
|
|
26
|
+
else
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_h
|
|
32
|
+
@data.transform_values { |v| unwrap_value(v) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def to_json(*args)
|
|
36
|
+
to_h.to_json(*args)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def to_s
|
|
40
|
+
"#<#{self.class} #{@data.map { |k, v| "#{k}=#{v.inspect}" }.join(" ")}>"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def inspect
|
|
44
|
+
to_s
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def key?(key)
|
|
48
|
+
@data.key?(key.to_s)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def keys
|
|
52
|
+
@data.keys
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def values
|
|
56
|
+
@data.values
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def each(&)
|
|
60
|
+
@data.each(&)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def wrap_value(value)
|
|
66
|
+
case value
|
|
67
|
+
when Hash
|
|
68
|
+
OverturoObject.new(value)
|
|
69
|
+
when Array
|
|
70
|
+
value.map { |v| wrap_value(v) }
|
|
71
|
+
else
|
|
72
|
+
value
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def unwrap_value(value)
|
|
77
|
+
case value
|
|
78
|
+
when OverturoObject
|
|
79
|
+
value.to_h
|
|
80
|
+
when Array
|
|
81
|
+
value.map { |v| unwrap_value(v) }
|
|
82
|
+
else
|
|
83
|
+
value
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Agree
|
|
6
|
+
class Agreements < ApiResource
|
|
7
|
+
include ApiOperations::Retrieve
|
|
8
|
+
include ApiOperations::List
|
|
9
|
+
|
|
10
|
+
RESOURCE_PATH = "/agreements"
|
|
11
|
+
OBJECT_KEY = "agreement"
|
|
12
|
+
LIST_KEY = "agreements"
|
|
13
|
+
|
|
14
|
+
collection_action :propose, method: :post
|
|
15
|
+
custom_action :counter, method: :post
|
|
16
|
+
custom_action :accept, method: :post
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Agree
|
|
6
|
+
class Collaborations < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
include ApiOperations::List
|
|
10
|
+
|
|
11
|
+
RESOURCE_PATH = "/collaborations"
|
|
12
|
+
OBJECT_KEY = "collaboration"
|
|
13
|
+
LIST_KEY = "collaborations"
|
|
14
|
+
|
|
15
|
+
custom_action :invite, method: :post, returns: :raw
|
|
16
|
+
custom_action :sign, method: :post
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Agree
|
|
6
|
+
# M-of-N quorum authorization on Agreement actions ("collective
|
|
7
|
+
# guardianship" per the Agree surface). Lives at /api/v1/quorum_requests;
|
|
8
|
+
# /api/v1/decisions is the separate decisions API.
|
|
9
|
+
class QuorumRequests < ApiResource
|
|
10
|
+
include ApiOperations::Create
|
|
11
|
+
include ApiOperations::Retrieve
|
|
12
|
+
include ApiOperations::List
|
|
13
|
+
|
|
14
|
+
RESOURCE_PATH = "/quorum_requests"
|
|
15
|
+
OBJECT_KEY = "quorum_request"
|
|
16
|
+
LIST_KEY = "quorum_requests"
|
|
17
|
+
|
|
18
|
+
custom_action :vote, method: :post
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Comply
|
|
6
|
+
class Anchors < ApiResource
|
|
7
|
+
include ApiOperations::Retrieve
|
|
8
|
+
|
|
9
|
+
RESOURCE_PATH = "/anchors"
|
|
10
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
11
|
+
declare_endpoint :get, "<resource>/{id}/receipts"
|
|
12
|
+
OBJECT_KEY = "anchor"
|
|
13
|
+
LIST_KEY = "anchors"
|
|
14
|
+
|
|
15
|
+
custom_action :export, method: :get, returns: :raw
|
|
16
|
+
|
|
17
|
+
def receipts(id, params = {})
|
|
18
|
+
receipts_path = "#{resource_path}/#{id}/receipts"
|
|
19
|
+
response = http_client.get(receipts_path, params: params)
|
|
20
|
+
unwrap_list(response, path: receipts_path, key: "receipts", params: params)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Comply
|
|
6
|
+
class CleanRooms < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
include ApiOperations::List
|
|
10
|
+
include ApiOperations::Delete
|
|
11
|
+
|
|
12
|
+
RESOURCE_PATH = "/clean_rooms"
|
|
13
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
14
|
+
declare_endpoint :post, "<resource>/{id}/queries"
|
|
15
|
+
declare_endpoint :get, "<resource>/{id}/queries"
|
|
16
|
+
declare_endpoint :get, "<resource>/{id}/queries/{query_id}"
|
|
17
|
+
OBJECT_KEY = "clean_room"
|
|
18
|
+
LIST_KEY = "clean_rooms"
|
|
19
|
+
|
|
20
|
+
custom_action :approve, method: :post
|
|
21
|
+
|
|
22
|
+
# Compute-to-data. Run a query inside the
|
|
23
|
+
# clean room and read its result. The result carries its privacy
|
|
24
|
+
# parameters (`k_anonymity_met`, `noise_parameters`) and a first-class
|
|
25
|
+
# `suppressed` flag + `suppression_reason`: a full k-anonymity
|
|
26
|
+
# suppression is surfaced honestly, never returned as a silent empty.
|
|
27
|
+
def run_query(id, params = {})
|
|
28
|
+
path = "#{resource_path}/#{id}/queries"
|
|
29
|
+
OverturoObject.new(http_client.post(path, body: params))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# GET /clean_rooms/:id/queries — list prior compute-to-data queries.
|
|
33
|
+
def queries(id, params = {})
|
|
34
|
+
path = "#{resource_path}/#{id}/queries"
|
|
35
|
+
unwrap_list(http_client.get(path, params: params), path: path, key: "queries", params: params)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# GET /clean_rooms/:id/queries/:query_id — read a single query result.
|
|
39
|
+
def query(id, query_id, params = {})
|
|
40
|
+
path = "#{resource_path}/#{id}/queries/#{query_id}"
|
|
41
|
+
OverturoObject.new(http_client.get(path, params: params))
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Comply
|
|
6
|
+
class EvidencePackages < ApiResource
|
|
7
|
+
include ApiOperations::Retrieve
|
|
8
|
+
|
|
9
|
+
RESOURCE_PATH = "/evidence_packages"
|
|
10
|
+
OBJECT_KEY = "evidence_package"
|
|
11
|
+
LIST_KEY = "evidence_packages"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Comply
|
|
6
|
+
# Read your residency posture: a per-country map of
|
|
7
|
+
# where your subjects' data is stored, the disclosure ledger, and an
|
|
8
|
+
# assurance status. Export a signed Proof of Residency. Singleton (no id).
|
|
9
|
+
class ResidencyPosture < ApiResource
|
|
10
|
+
RESOURCE_PATH = "/residency_posture"
|
|
11
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
12
|
+
declare_endpoint :get, "<resource>"
|
|
13
|
+
declare_endpoint :post, "<resource>/evidence_package"
|
|
14
|
+
OBJECT_KEY = "residency_posture"
|
|
15
|
+
|
|
16
|
+
# GET /residency_posture — the per-country posture + assurance status.
|
|
17
|
+
def get(params = {})
|
|
18
|
+
response = http_client.get(resource_path, params: params)
|
|
19
|
+
OverturoObject.new(response)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# POST /residency_posture/evidence_package — the signed, anchored Proof
|
|
23
|
+
# of Residency, on the same verifiable path as the transfer register.
|
|
24
|
+
def evidence_package(params = {})
|
|
25
|
+
response = http_client.post("#{resource_path}/evidence_package", body: params)
|
|
26
|
+
OverturoObject.new(response)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Comply
|
|
6
|
+
# Read the cross-border transfer register and export
|
|
7
|
+
# its signed, verifiable evidence package. Each entry carries the lawful
|
|
8
|
+
# basis it relied on, the adequacy verdict, and the country pair. Read and
|
|
9
|
+
# export only — the SDK never creates a transfer.
|
|
10
|
+
class TransferRegister < ApiResource
|
|
11
|
+
include ApiOperations::List
|
|
12
|
+
|
|
13
|
+
RESOURCE_PATH = "/transfer_register"
|
|
14
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
15
|
+
declare_endpoint :post, "<resource>/evidence_package"
|
|
16
|
+
OBJECT_KEY = "transfer"
|
|
17
|
+
LIST_KEY = "transfers"
|
|
18
|
+
|
|
19
|
+
# POST /transfer_register/evidence_package — the signed, anchored,
|
|
20
|
+
# independently-verifiable evidence package of the register.
|
|
21
|
+
def evidence_package(params = {})
|
|
22
|
+
response = http_client.post("#{resource_path}/evidence_package", body: params)
|
|
23
|
+
OverturoObject.new(response)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Connect
|
|
6
|
+
# Only the `publish` and `unpublish` member actions exist at the top
|
|
7
|
+
# level. Creating an application happens via the dashboard; per-application
|
|
8
|
+
# configuration uses the nested `applications/:id/...` resources — see
|
|
9
|
+
# Connect::Webhooks and Connect::Flows.
|
|
10
|
+
class Applications < ApiResource
|
|
11
|
+
RESOURCE_PATH = "/applications"
|
|
12
|
+
OBJECT_KEY = "application"
|
|
13
|
+
LIST_KEY = "applications"
|
|
14
|
+
|
|
15
|
+
custom_action :publish, method: :post
|
|
16
|
+
custom_action :unpublish, method: :post
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Connect
|
|
6
|
+
class Connections < ApiResource
|
|
7
|
+
include ApiOperations::Retrieve
|
|
8
|
+
include ApiOperations::List
|
|
9
|
+
include ApiOperations::Delete
|
|
10
|
+
|
|
11
|
+
RESOURCE_PATH = "/connections"
|
|
12
|
+
OBJECT_KEY = "connection"
|
|
13
|
+
LIST_KEY = "connections"
|
|
14
|
+
|
|
15
|
+
custom_action :suspend, method: :post
|
|
16
|
+
custom_action :unsuspend, method: :post
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Connect
|
|
6
|
+
# Flows are nested under applications:
|
|
7
|
+
# /api/v1/applications/:application_id/flows[/:id][/<action>]
|
|
8
|
+
class Flows < ApiResource
|
|
9
|
+
include ApiOperations::NestedResource
|
|
10
|
+
|
|
11
|
+
RESOURCE_PATH = "/applications"
|
|
12
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
13
|
+
declare_endpoint :post, "<resource>/{application_id}/flows/{id}/activate"
|
|
14
|
+
declare_endpoint :post, "<resource>/{application_id}/flows/{id}/deprecate"
|
|
15
|
+
declare_endpoint :post, "<resource>/{application_id}/flows/{id}/archive"
|
|
16
|
+
declare_endpoint :post, "<resource>/{application_id}/flows/{id}/resolve_preview"
|
|
17
|
+
OBJECT_KEY = "flow"
|
|
18
|
+
LIST_KEY = "flows"
|
|
19
|
+
|
|
20
|
+
nested_resource :flow,
|
|
21
|
+
path: "flows",
|
|
22
|
+
object_key: "flow",
|
|
23
|
+
list_key: "flows",
|
|
24
|
+
operations: %i[create retrieve list update delete]
|
|
25
|
+
|
|
26
|
+
# Public API aliases — take (application_id, ...) as first arg.
|
|
27
|
+
def create(application_id, params = {})
|
|
28
|
+
create_flow(application_id, params)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def retrieve(application_id, id)
|
|
32
|
+
retrieve_flow(application_id, id)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def list(application_id, params = {})
|
|
36
|
+
list_flows(application_id, params)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def update(application_id, id, params = {})
|
|
40
|
+
update_flow(application_id, id, params)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def delete(application_id, id)
|
|
44
|
+
delete_flow(application_id, id)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Member actions on the nested resource. NestedResource doesn't have a
|
|
48
|
+
# `nested_custom_action` helper yet, so these are written explicitly.
|
|
49
|
+
def activate(application_id, id, params = {})
|
|
50
|
+
member_action(application_id, id, "activate", params)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def deprecate(application_id, id, params = {})
|
|
54
|
+
member_action(application_id, id, "deprecate", params)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def archive(application_id, id, params = {})
|
|
58
|
+
member_action(application_id, id, "archive", params)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def resolve_preview(application_id, id, params = {})
|
|
62
|
+
member_action(application_id, id, "resolve_preview", params)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def member_action(application_id, id, action, params)
|
|
68
|
+
response = http_client.post(
|
|
69
|
+
"#{RESOURCE_PATH}/#{application_id}/flows/#{id}/#{action}",
|
|
70
|
+
body: params
|
|
71
|
+
)
|
|
72
|
+
unwrap(response)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|