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,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Connect
|
|
6
|
+
# Meetings are nested under applications:
|
|
7
|
+
# /api/v1/applications/:application_id/meeting_consents[/:id][/participants]
|
|
8
|
+
#
|
|
9
|
+
# A meeting is the unit of record: it has a window (scheduled_at / ends_at),
|
|
10
|
+
# a platform identity, a cancellation, and participant rows that carry
|
|
11
|
+
# each person's decision per purpose.
|
|
12
|
+
class MeetingConsents < ApiResource
|
|
13
|
+
include ApiOperations::NestedResource
|
|
14
|
+
|
|
15
|
+
RESOURCE_PATH = "/applications"
|
|
16
|
+
declare_endpoint :get, "<resource>/{application_id}/meeting_consents/{id}/participants"
|
|
17
|
+
OBJECT_KEY = "meeting_consent"
|
|
18
|
+
LIST_KEY = "meeting_consents"
|
|
19
|
+
|
|
20
|
+
nested_resource :meeting_consent,
|
|
21
|
+
path: "meeting_consents",
|
|
22
|
+
object_key: "meeting_consent",
|
|
23
|
+
list_key: "meeting_consents",
|
|
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_meeting_consent(application_id, params)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def retrieve(application_id, id)
|
|
32
|
+
retrieve_meeting_consent(application_id, id)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def list(application_id, params = {})
|
|
36
|
+
list_meeting_consents(application_id, params)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Rename or reschedule (title, scheduled_at, duration_minutes, platform,
|
|
40
|
+
# external_meeting_id).
|
|
41
|
+
def update(application_id, id, params = {})
|
|
42
|
+
update_meeting_consent(application_id, id, params)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Cancels the meeting (participants are told; the record stays).
|
|
46
|
+
def cancel(application_id, id)
|
|
47
|
+
delete_meeting_consent(application_id, id)
|
|
48
|
+
end
|
|
49
|
+
alias delete cancel
|
|
50
|
+
|
|
51
|
+
# The meeting's participants with their decisions per purpose.
|
|
52
|
+
def participants(application_id, id, params = {})
|
|
53
|
+
path = "#{RESOURCE_PATH}/#{application_id}/meeting_consents/#{id}/participants"
|
|
54
|
+
response = http_client.get(path, params: params)
|
|
55
|
+
unwrap_list(response, path: path, key: "participants", params: params)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Connect
|
|
6
|
+
# Data portability (GDPR Art. 20). List the supported
|
|
7
|
+
# export formats and confirm a cross-border export/import. The self-service
|
|
8
|
+
# *access* DSAR is a web-only export and is not part of the API surface.
|
|
9
|
+
#
|
|
10
|
+
# Application-scoped: every call takes the application_id as its first
|
|
11
|
+
# argument and resolves under /applications/:application_id/portability.
|
|
12
|
+
class Portability < ApiResource
|
|
13
|
+
RESOURCE_PATH = "/applications"
|
|
14
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
15
|
+
declare_endpoint :get, "<resource>/{application_id}/portability/formats"
|
|
16
|
+
declare_endpoint :post, "<resource>/{application_id}/portability/confirm_export"
|
|
17
|
+
declare_endpoint :post, "<resource>/{application_id}/portability/confirm_import"
|
|
18
|
+
|
|
19
|
+
# GET /applications/:application_id/portability/formats — the supported
|
|
20
|
+
# portability formats.
|
|
21
|
+
def formats(application_id, params = {})
|
|
22
|
+
OverturoObject.new(http_client.get(portability_path(application_id, "formats"), params: params))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# POST /applications/:application_id/portability/confirm_export —
|
|
26
|
+
# confirm and forward the export.
|
|
27
|
+
def confirm_export(application_id, params = {})
|
|
28
|
+
OverturoObject.new(http_client.post(portability_path(application_id, "confirm_export"), body: params))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# POST /applications/:application_id/portability/confirm_import —
|
|
32
|
+
# confirm an import.
|
|
33
|
+
def confirm_import(application_id, params = {})
|
|
34
|
+
OverturoObject.new(http_client.post(portability_path(application_id, "confirm_import"), body: params))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def portability_path(application_id, action)
|
|
40
|
+
"#{resource_path}/#{application_id}/portability/#{action}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Connect
|
|
6
|
+
class Webhooks < ApiResource
|
|
7
|
+
include ApiOperations::NestedResource
|
|
8
|
+
|
|
9
|
+
RESOURCE_PATH = "/applications"
|
|
10
|
+
OBJECT_KEY = "webhook_subscription"
|
|
11
|
+
LIST_KEY = "webhook_subscriptions"
|
|
12
|
+
|
|
13
|
+
nested_resource :webhook,
|
|
14
|
+
path: "webhooks",
|
|
15
|
+
object_key: "webhook_subscription",
|
|
16
|
+
list_key: "webhook_subscriptions",
|
|
17
|
+
operations: %i[create retrieve list update delete]
|
|
18
|
+
|
|
19
|
+
# Public API aliases: take (application_id, ...) as first arg
|
|
20
|
+
def create(application_id, params = {})
|
|
21
|
+
create_webhook(application_id, params)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def retrieve(application_id, id)
|
|
25
|
+
retrieve_webhook(application_id, id)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def list(application_id, params = {})
|
|
29
|
+
list_webhooks(application_id, params)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def update(application_id, id, params = {})
|
|
33
|
+
update_webhook(application_id, id, params)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def delete(application_id, id)
|
|
37
|
+
delete_webhook(application_id, id)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cgi"
|
|
4
|
+
|
|
5
|
+
module Overturo
|
|
6
|
+
module Resources
|
|
7
|
+
module Consent
|
|
8
|
+
# 201 — consent records captured outside Overturo's surfaces: the Record
|
|
9
|
+
# API (create = capture + commit in one call, idempotent on your key),
|
|
10
|
+
# the read, the batch import with its dry run, and the status read by
|
|
11
|
+
# the subject reference you supplied (email or your own identifier).
|
|
12
|
+
class ConsentRecords < ApiResource
|
|
13
|
+
include ApiOperations::Create
|
|
14
|
+
include ApiOperations::Retrieve
|
|
15
|
+
|
|
16
|
+
RESOURCE_PATH = "/consent_records"
|
|
17
|
+
OBJECT_KEY = "consent_record"
|
|
18
|
+
LIST_KEY = "consent_records"
|
|
19
|
+
|
|
20
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
21
|
+
declare_endpoint :post, "<resource>/imports"
|
|
22
|
+
declare_endpoint :get, "<resource>/imports/{import_id}"
|
|
23
|
+
declare_endpoint :get, "/applications/{application_id}/consent_status"
|
|
24
|
+
|
|
25
|
+
# Import consents you already hold (at most 5000 rows per batch).
|
|
26
|
+
# Returns the import (status pending); read it with #import_status.
|
|
27
|
+
def import(flow_id:, records:, dry_run: false, send_receipts: false)
|
|
28
|
+
raise ArgumentError, "flow_id is required" if flow_id.nil? || flow_id.to_s.empty?
|
|
29
|
+
raise ArgumentError, "records must be a non-empty array" unless records.is_a?(Array) && records.any?
|
|
30
|
+
|
|
31
|
+
response = http_client.post("#{resource_path}/imports",
|
|
32
|
+
body: { flow_id: flow_id, records: records, dry_run: dry_run, send_receipts: send_receipts })
|
|
33
|
+
unwrap(response, "import")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def import_status(import_id)
|
|
37
|
+
raise ArgumentError, "import_id is required" if import_id.nil? || import_id.to_s.empty?
|
|
38
|
+
|
|
39
|
+
unwrap(http_client.get("#{resource_path}/imports/#{CGI.escape(import_id.to_s)}"), "import")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# The per-purpose consent status for a subject reference.
|
|
43
|
+
def status(application_id:, email: nil, external_id: nil)
|
|
44
|
+
raise ArgumentError, "application_id is required" if application_id.nil? || application_id.to_s.empty?
|
|
45
|
+
raise ArgumentError, "email or external_id is required" if email.to_s.empty? && external_id.to_s.empty?
|
|
46
|
+
|
|
47
|
+
# Flat bracket keys: the query is `subject[email]=…`, the shape the server reads.
|
|
48
|
+
params = {}
|
|
49
|
+
params["subject[email]"] = email unless email.to_s.empty?
|
|
50
|
+
params["subject[external_id]"] = external_id unless external_id.to_s.empty?
|
|
51
|
+
response = http_client.get("/applications/#{CGI.escape(application_id.to_s)}/consent_status", params: params)
|
|
52
|
+
OverturoObject.new(response)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Consent
|
|
6
|
+
class ConsentSessions < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
|
|
10
|
+
RESOURCE_PATH = "/consent_sessions"
|
|
11
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
12
|
+
declare_endpoint :post, "<resource>/{id}/exchange"
|
|
13
|
+
OBJECT_KEY = "consent_session"
|
|
14
|
+
LIST_KEY = "consent_sessions"
|
|
15
|
+
|
|
16
|
+
custom_action :authorize, method: :post
|
|
17
|
+
custom_action :verify, method: :get
|
|
18
|
+
|
|
19
|
+
# Exchange a consent token for claims, attestations, credentials, and tokens.
|
|
20
|
+
# Handles HTTP 202 (fulfillment pending) transparently by retrying with
|
|
21
|
+
# the Retry-After interval until the server returns the full result.
|
|
22
|
+
def exchange(id, params = {})
|
|
23
|
+
max_retries = 5
|
|
24
|
+
path = "#{resource_path}/#{id}/exchange"
|
|
25
|
+
|
|
26
|
+
(max_retries + 1).times do |attempt|
|
|
27
|
+
response = http_client.post(path, body: params)
|
|
28
|
+
|
|
29
|
+
# HttpClient returns parsed JSON for all 2xx responses.
|
|
30
|
+
# A 202 returns {status: "pending", ...} — detect and retry.
|
|
31
|
+
if response.is_a?(Hash) && response["status"] == "pending"
|
|
32
|
+
if attempt == max_retries
|
|
33
|
+
raise Overturo::ApiError.new(
|
|
34
|
+
"Exchange timeout: fulfillment still pending",
|
|
35
|
+
http_status: 202
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
sleep(1)
|
|
40
|
+
next
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
return OverturoObject.new(response)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cgi"
|
|
4
|
+
|
|
5
|
+
module Overturo
|
|
6
|
+
module Resources
|
|
7
|
+
module Consent
|
|
8
|
+
# 189 — pre-flight disclosure discovery. Returns what the decision screen
|
|
9
|
+
# would present for a consent flow (purposes, fields, steps, the action
|
|
10
|
+
# label, expiry, application branding) BEFORE any session exists, in public
|
|
11
|
+
# vocabulary and the requested locale.
|
|
12
|
+
#
|
|
13
|
+
# Publishable-key authenticated: the publishable key (pk_live_… / pk_test_…)
|
|
14
|
+
# is an embed-safe, per-application credential passed EXPLICITLY per call
|
|
15
|
+
# rather than via client config — this endpoint ignores the client's bearer
|
|
16
|
+
# token, so the publishable key is the only credential that matters. An
|
|
17
|
+
# unknown / foreign / non-consent flow answers a uniform 404
|
|
18
|
+
# (Overturo::NotFoundError).
|
|
19
|
+
class Decisions < ApiResource
|
|
20
|
+
RESOURCE_PATH = "/decisions"
|
|
21
|
+
OBJECT_KEY = "decision"
|
|
22
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
23
|
+
declare_endpoint :get, "<resource>/flows/{flow_id}/disclosures"
|
|
24
|
+
|
|
25
|
+
# 201 — commit a capture: your server received the capture token with the
|
|
26
|
+
# form submission and commits it with the application credential
|
|
27
|
+
# (`authorize(token, subject: {email:, external_id:}, suppress_receipt: false)`).
|
|
28
|
+
# The result carries `status`, `record_id` and the receipt `channel`. A
|
|
29
|
+
# publishable key cannot commit (403 publishable_key_cannot_commit).
|
|
30
|
+
custom_action :authorize, method: :post
|
|
31
|
+
|
|
32
|
+
def discover(flow_id, publishable_key:, locale: nil)
|
|
33
|
+
raise ArgumentError, "flow_id is required" if flow_id.nil? || flow_id.to_s.empty?
|
|
34
|
+
raise ArgumentError, "publishable_key is required" if publishable_key.nil? || publishable_key.to_s.empty?
|
|
35
|
+
|
|
36
|
+
path = "#{resource_path}/flows/#{CGI.escape(flow_id.to_s)}/disclosures"
|
|
37
|
+
# Only send ?locale= for a non-blank locale (in Ruby "" is truthy, so a
|
|
38
|
+
# bare truthiness check would emit ?locale= — the JS/py clients omit it).
|
|
39
|
+
params = locale.to_s.empty? ? {} : { locale: locale }
|
|
40
|
+
response = http_client.get(path, params: params, headers: { "X-Publishable-Key" => publishable_key })
|
|
41
|
+
|
|
42
|
+
# The server wraps the inventory as {"flow" => {...}}; return the
|
|
43
|
+
# inventory itself, matching the JS/py/node
|
|
44
|
+
# clients' `envelope.flow`. An envelope-less 200 (a proxy/gateway
|
|
45
|
+
# misconfig — the server is fail-closed) is a typed error, never a
|
|
46
|
+
# silent pass-through of the whole body dressed up as the inventory.
|
|
47
|
+
raise Overturo::ApiError, "Malformed discovery response: missing 'flow' in body" unless response.is_a?(Hash) && response.key?("flow")
|
|
48
|
+
|
|
49
|
+
OverturoObject.new(response.fetch("flow"))
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Consent
|
|
6
|
+
class Entitlements < ApiResource
|
|
7
|
+
include ApiOperations::Retrieve
|
|
8
|
+
include ApiOperations::List
|
|
9
|
+
|
|
10
|
+
RESOURCE_PATH = "/entitlements"
|
|
11
|
+
OBJECT_KEY = "entitlement"
|
|
12
|
+
LIST_KEY = "entitlements"
|
|
13
|
+
|
|
14
|
+
custom_action :verify, method: :get, returns: :raw
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Consent
|
|
6
|
+
class TrustLevels < ApiResource
|
|
7
|
+
include ApiOperations::Retrieve
|
|
8
|
+
include ApiOperations::List
|
|
9
|
+
|
|
10
|
+
RESOURCE_PATH = "/trust_levels"
|
|
11
|
+
OBJECT_KEY = "trust_level"
|
|
12
|
+
LIST_KEY = "trust_levels"
|
|
13
|
+
|
|
14
|
+
custom_action :trigger, method: :post
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Core
|
|
6
|
+
# The accounts API is list-only. Account creation happens through the
|
|
7
|
+
# dashboard signup flow, not the API, and per-account configuration is
|
|
8
|
+
# managed server-side.
|
|
9
|
+
class Accounts < ApiResource
|
|
10
|
+
include ApiOperations::List
|
|
11
|
+
|
|
12
|
+
RESOURCE_PATH = "/accounts"
|
|
13
|
+
OBJECT_KEY = "account"
|
|
14
|
+
LIST_KEY = "accounts"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Core
|
|
6
|
+
class Me < ApiResource
|
|
7
|
+
RESOURCE_PATH = "/me"
|
|
8
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
9
|
+
declare_endpoint :get, "<resource>"
|
|
10
|
+
OBJECT_KEY = "user"
|
|
11
|
+
LIST_KEY = nil
|
|
12
|
+
|
|
13
|
+
def retrieve
|
|
14
|
+
response = http_client.get(resource_path)
|
|
15
|
+
unwrap(response)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Delegate
|
|
6
|
+
class AgentIdentities < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
include ApiOperations::List
|
|
10
|
+
include ApiOperations::Update
|
|
11
|
+
include ApiOperations::Delete
|
|
12
|
+
|
|
13
|
+
RESOURCE_PATH = "/agent_identities"
|
|
14
|
+
OBJECT_KEY = "agent_identity"
|
|
15
|
+
LIST_KEY = "agent_identities"
|
|
16
|
+
|
|
17
|
+
custom_action :delegate, method: :post
|
|
18
|
+
custom_action :suspend, method: :post
|
|
19
|
+
custom_action :reactivate, method: :post
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Delegate
|
|
6
|
+
# Durable authorization records — `GET /api/v1/authorization_receipts/:id`.
|
|
7
|
+
# Requires the
|
|
8
|
+
# `audit:verify` token scope. The 404 contract is parity-preserving by
|
|
9
|
+
# design: unknown, foreign-account, and non-authority ids are
|
|
10
|
+
# indistinguishable — don't try to disambiguate client-side.
|
|
11
|
+
class AuthorizationReceipts < ApiResource
|
|
12
|
+
RESOURCE_PATH = "/authorization_receipts"
|
|
13
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
14
|
+
declare_endpoint :get, "<resource>/{id}"
|
|
15
|
+
OBJECT_KEY = "authorization_receipt"
|
|
16
|
+
|
|
17
|
+
# flavor:
|
|
18
|
+
# nil / "canonical" — the wrapped document (unwrapped to an
|
|
19
|
+
# OverturoObject here, like every other resource read)
|
|
20
|
+
# "signed" — the bare signed envelope, returned as a plain Hash:
|
|
21
|
+
# it is a portable artifact you hand to a record verifier or
|
|
22
|
+
# write to disk, not an API object
|
|
23
|
+
# "dpv" — the JSON-LD document, also a plain Hash (the server
|
|
24
|
+
# responds with application/ld+json; the body is JSON)
|
|
25
|
+
#
|
|
26
|
+
# Typed refusals (422) surface as Overturo::InvalidRequestError with
|
|
27
|
+
# `error_code` — "unknown_flavor", "not_signable", "dpv_unavailable".
|
|
28
|
+
def retrieve(id, flavor: nil)
|
|
29
|
+
params = flavor ? { flavor: flavor } : {}
|
|
30
|
+
response = http_client.get("#{RESOURCE_PATH}/#{id}", params: params)
|
|
31
|
+
return unwrap(response) if flavor.nil? || flavor.to_s == "canonical"
|
|
32
|
+
|
|
33
|
+
response
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Delegate
|
|
6
|
+
# `/api/v1/delegations` supports index/create/show/update. There is **no**
|
|
7
|
+
# bare DELETE endpoint — delegations are torn down via the `/revoke`
|
|
8
|
+
# member action, which is mounted as `DELETE /delegations/:id/revoke`
|
|
9
|
+
# (the verb encodes destruction; the path encodes that revocation is a
|
|
10
|
+
# specific lifecycle event distinct from a hard delete).
|
|
11
|
+
class Delegations < ApiResource
|
|
12
|
+
include ApiOperations::Create
|
|
13
|
+
include ApiOperations::Retrieve
|
|
14
|
+
include ApiOperations::List
|
|
15
|
+
include ApiOperations::Update
|
|
16
|
+
|
|
17
|
+
RESOURCE_PATH = "/delegations"
|
|
18
|
+
# 193 D12 — endpoints built by explicit http_client calls below.
|
|
19
|
+
declare_endpoint :delete, "<resource>/{id}/revoke"
|
|
20
|
+
OBJECT_KEY = "delegation_grant"
|
|
21
|
+
LIST_KEY = "delegation_grants"
|
|
22
|
+
|
|
23
|
+
# Revoke uses DELETE on a member sub-path. `custom_action` only knows
|
|
24
|
+
# :get and :post, so this is written explicitly. `http_client.delete`
|
|
25
|
+
# doesn't accept a body or params — the action takes the id and that's
|
|
26
|
+
# the entire contract.
|
|
27
|
+
def revoke(id)
|
|
28
|
+
response = http_client.delete("#{RESOURCE_PATH}/#{id}/revoke")
|
|
29
|
+
unwrap(response)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Delegate
|
|
6
|
+
# Operator-declared disclosure receipts — `POST /api/v1/disclosure_receipts`.
|
|
7
|
+
# Requires the `disclosures:write`
|
|
8
|
+
# token scope. Mint-only by design: the operator disclosure log page is the
|
|
9
|
+
# read side (programmatic reads are a registered deferred capability).
|
|
10
|
+
#
|
|
11
|
+
# Payload: flow_id, agent_id, disclosed_at (ISO 8601), optional locale.
|
|
12
|
+
# The 201 unwraps to {record_id:, record:}. Typed refusals (422) surface
|
|
13
|
+
# as Overturo::InvalidRequestError with `error_code` — this endpoint's
|
|
14
|
+
# shape is {"error" => <human message>, "code" => <machine code>}
|
|
15
|
+
# ("agent_not_disclosed", "invalid_disclosed_at", "purposes_missing").
|
|
16
|
+
class DisclosureReceipts < ApiResource
|
|
17
|
+
include ApiOperations::Create
|
|
18
|
+
|
|
19
|
+
RESOURCE_PATH = "/disclosure_receipts"
|
|
20
|
+
OBJECT_KEY = "disclosure_receipt"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Delegate
|
|
6
|
+
class SecurityEventStreams < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
include ApiOperations::List
|
|
10
|
+
include ApiOperations::Update
|
|
11
|
+
include ApiOperations::Delete
|
|
12
|
+
|
|
13
|
+
RESOURCE_PATH = "/security_event_streams"
|
|
14
|
+
OBJECT_KEY = "security_event_stream"
|
|
15
|
+
LIST_KEY = "security_event_streams"
|
|
16
|
+
|
|
17
|
+
custom_action :verify, method: :post, returns: :raw
|
|
18
|
+
custom_action :poll, method: :get, returns: :raw
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Protect
|
|
6
|
+
class DataLicenses < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
include ApiOperations::List
|
|
10
|
+
|
|
11
|
+
RESOURCE_PATH = "/data_licenses"
|
|
12
|
+
OBJECT_KEY = "data_license"
|
|
13
|
+
LIST_KEY = "data_licenses"
|
|
14
|
+
|
|
15
|
+
custom_action :terminate, method: :post
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Protect
|
|
6
|
+
class DataRequests < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
include ApiOperations::List
|
|
10
|
+
|
|
11
|
+
RESOURCE_PATH = "/data_requests"
|
|
12
|
+
OBJECT_KEY = "data_request"
|
|
13
|
+
LIST_KEY = "data_requests"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Protect
|
|
6
|
+
class Policies < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
include ApiOperations::List
|
|
10
|
+
include ApiOperations::Update
|
|
11
|
+
include ApiOperations::Delete
|
|
12
|
+
|
|
13
|
+
RESOURCE_PATH = "/policies"
|
|
14
|
+
OBJECT_KEY = "policy"
|
|
15
|
+
LIST_KEY = "policies"
|
|
16
|
+
|
|
17
|
+
custom_action :activate, method: :post
|
|
18
|
+
custom_action :revoke, method: :post
|
|
19
|
+
custom_action :share, method: :post, returns: :raw
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Protect
|
|
6
|
+
class Transfers < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
include ApiOperations::List
|
|
10
|
+
|
|
11
|
+
RESOURCE_PATH = "/transfers"
|
|
12
|
+
OBJECT_KEY = "transfer"
|
|
13
|
+
LIST_KEY = "transfers"
|
|
14
|
+
|
|
15
|
+
custom_action :cancel, method: :post
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Verify
|
|
6
|
+
# `/api/v1/credentials` supports index/create/show/destroy plus the
|
|
7
|
+
# `/wallet_pass` member action. There is **no** PATCH endpoint —
|
|
8
|
+
# credentials are immutable once issued.
|
|
9
|
+
class Credentials < ApiResource
|
|
10
|
+
include ApiOperations::Create
|
|
11
|
+
include ApiOperations::Retrieve
|
|
12
|
+
include ApiOperations::List
|
|
13
|
+
include ApiOperations::Delete
|
|
14
|
+
|
|
15
|
+
RESOURCE_PATH = "/credentials"
|
|
16
|
+
OBJECT_KEY = "credential"
|
|
17
|
+
LIST_KEY = "credentials"
|
|
18
|
+
|
|
19
|
+
custom_action :wallet_pass, method: :get, returns: :raw
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Overturo
|
|
4
|
+
module Resources
|
|
5
|
+
module Verify
|
|
6
|
+
class Presentations < ApiResource
|
|
7
|
+
include ApiOperations::Create
|
|
8
|
+
include ApiOperations::Retrieve
|
|
9
|
+
|
|
10
|
+
RESOURCE_PATH = "/presentations"
|
|
11
|
+
OBJECT_KEY = "presentation"
|
|
12
|
+
LIST_KEY = "presentations"
|
|
13
|
+
|
|
14
|
+
custom_action :present, method: :patch, returns: :raw
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|