dinie-sdk 1.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +12 -0
- data/LICENSE +21 -0
- data/README.md +280 -0
- data/lib/dinie/generated/api_version.rb +8 -0
- data/lib/dinie/generated/client.rb +96 -0
- data/lib/dinie/generated/errors/registry.rb +40 -0
- data/lib/dinie/generated/events/base.rb +11 -0
- data/lib/dinie/generated/events/credit_offer.rb +56 -0
- data/lib/dinie/generated/events/customer_created.rb +42 -0
- data/lib/dinie/generated/events/customer_denied.rb +39 -0
- data/lib/dinie/generated/events/customer_kyc_updated.rb +36 -0
- data/lib/dinie/generated/events/customer_status.rb +48 -0
- data/lib/dinie/generated/events/deserializers.rb +35 -0
- data/lib/dinie/generated/events/loan_active.rb +35 -0
- data/lib/dinie/generated/events/loan_created.rb +38 -0
- data/lib/dinie/generated/events/loan_payment_received.rb +46 -0
- data/lib/dinie/generated/events/loan_processing.rb +37 -0
- data/lib/dinie/generated/events/loan_signature_received.rb +48 -0
- data/lib/dinie/generated/events/loan_status.rb +73 -0
- data/lib/dinie/generated/events.rb +4 -0
- data/lib/dinie/generated/resources/banks.rb +25 -0
- data/lib/dinie/generated/resources/biometrics.rb +27 -0
- data/lib/dinie/generated/resources/credentials.rb +56 -0
- data/lib/dinie/generated/resources/credit_offers.rb +59 -0
- data/lib/dinie/generated/resources/customers.rb +200 -0
- data/lib/dinie/generated/resources/loans.rb +70 -0
- data/lib/dinie/generated/resources/webhook_endpoints.rb +97 -0
- data/lib/dinie/generated/resources.rb +9 -0
- data/lib/dinie/generated/types/bank.rb +17 -0
- data/lib/dinie/generated/types/biometrics_session.rb +16 -0
- data/lib/dinie/generated/types/biometrics_session_exchange_response.rb +23 -0
- data/lib/dinie/generated/types/credential.rb +50 -0
- data/lib/dinie/generated/types/credit_offer.rb +62 -0
- data/lib/dinie/generated/types/customer.rb +45 -0
- data/lib/dinie/generated/types/customer_bank_account.rb +33 -0
- data/lib/dinie/generated/types/ids.rb +18 -0
- data/lib/dinie/generated/types/kyc.rb +458 -0
- data/lib/dinie/generated/types/kyc_attachment_response.rb +16 -0
- data/lib/dinie/generated/types/loan.rb +51 -0
- data/lib/dinie/generated/types/money.rb +4 -0
- data/lib/dinie/generated/types/simulation.rb +35 -0
- data/lib/dinie/generated/types/transaction.rb +43 -0
- data/lib/dinie/generated/types/webhook_endpoint.rb +52 -0
- data/lib/dinie/generated/types/webhook_secret_rotation.rb +17 -0
- data/lib/dinie/generated/types.rb +18 -0
- data/lib/dinie/runtime/errors.rb +295 -0
- data/lib/dinie/runtime/http.rb +325 -0
- data/lib/dinie/runtime/idempotency.rb +34 -0
- data/lib/dinie/runtime/logger.rb +326 -0
- data/lib/dinie/runtime/model.rb +162 -0
- data/lib/dinie/runtime/multipart.rb +77 -0
- data/lib/dinie/runtime/paginator.rb +164 -0
- data/lib/dinie/runtime/rate_limit.rb +150 -0
- data/lib/dinie/runtime/request_options.rb +112 -0
- data/lib/dinie/runtime/retry.rb +74 -0
- data/lib/dinie/runtime/token_manager.rb +341 -0
- data/lib/dinie/runtime/webhooks.rb +194 -0
- data/lib/dinie/version.rb +7 -0
- data/lib/dinie.rb +36 -0
- data/sig/_external/faraday.rbs +44 -0
- data/sig/dinie/generated/client.rbs +45 -0
- data/sig/dinie/generated/errors/registry.rbs +40 -0
- data/sig/dinie/generated/events/base.rbs +17 -0
- data/sig/dinie/generated/events/credit_offer.rbs +33 -0
- data/sig/dinie/generated/events/customer_created.rbs +27 -0
- data/sig/dinie/generated/events/customer_denied.rbs +25 -0
- data/sig/dinie/generated/events/customer_kyc_updated.rbs +21 -0
- data/sig/dinie/generated/events/customer_status.rbs +26 -0
- data/sig/dinie/generated/events/deserializers.rbs +9 -0
- data/sig/dinie/generated/events/loan_active.rbs +20 -0
- data/sig/dinie/generated/events/loan_created.rbs +23 -0
- data/sig/dinie/generated/events/loan_payment_received.rbs +28 -0
- data/sig/dinie/generated/events/loan_processing.rbs +23 -0
- data/sig/dinie/generated/events/loan_signature_received.rbs +30 -0
- data/sig/dinie/generated/events/loan_status.rbs +40 -0
- data/sig/dinie/generated/resources/banks.rbs +15 -0
- data/sig/dinie/generated/resources/credentials.rbs +21 -0
- data/sig/dinie/generated/resources/credit_offers.rbs +19 -0
- data/sig/dinie/generated/resources/customers.rbs +58 -0
- data/sig/dinie/generated/resources/loans.rbs +26 -0
- data/sig/dinie/generated/resources/webhook_endpoints.rbs +35 -0
- data/sig/dinie/generated/types/bank.rbs +12 -0
- data/sig/dinie/generated/types/biometrics_session.rbs +11 -0
- data/sig/dinie/generated/types/credential.rbs +26 -0
- data/sig/dinie/generated/types/credit_offer.rbs +24 -0
- data/sig/dinie/generated/types/customer.rbs +25 -0
- data/sig/dinie/generated/types/customer_bank_account.rbs +26 -0
- data/sig/dinie/generated/types/enums.rbs +66 -0
- data/sig/dinie/generated/types/ids.rbs +21 -0
- data/sig/dinie/generated/types/kyc/attachment.rbs +14 -0
- data/sig/dinie/generated/types/kyc/common.rbs +42 -0
- data/sig/dinie/generated/types/kyc/requirements.rbs +117 -0
- data/sig/dinie/generated/types/kyc/submitted.rbs +21 -0
- data/sig/dinie/generated/types/kyc/uploads.rbs +24 -0
- data/sig/dinie/generated/types/loan.rbs +32 -0
- data/sig/dinie/generated/types/money.rbs +6 -0
- data/sig/dinie/generated/types/simulation.rbs +28 -0
- data/sig/dinie/generated/types/transaction.rbs +24 -0
- data/sig/dinie/generated/types/webhook_endpoint.rbs +38 -0
- data/sig/dinie/runtime/errors.rbs +106 -0
- data/sig/dinie/runtime/http.rbs +59 -0
- data/sig/dinie/runtime/idempotency.rbs +15 -0
- data/sig/dinie/runtime/logger.rbs +89 -0
- data/sig/dinie/runtime/model.rbs +51 -0
- data/sig/dinie/runtime/multipart.rbs +25 -0
- data/sig/dinie/runtime/paginator.rbs +50 -0
- data/sig/dinie/runtime/rate_limit.rbs +46 -0
- data/sig/dinie/runtime/request_options.rbs +35 -0
- data/sig/dinie/runtime/retry.rbs +29 -0
- data/sig/dinie/runtime/token_manager.rbs +51 -0
- data/sig/dinie/runtime/webhooks.rbs +31 -0
- data/sig/dinie/version.rbs +7 -0
- metadata +316 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Leveled logging + PII redaction (architecture §9, RB12). Mirrors `lib/dinie/runtime/logger.rb`.
|
|
2
|
+
# Runtime-internal. `Middleware::Logging` subclasses `Faraday::Middleware` (untyped — no bundled
|
|
3
|
+
# RBS; the informative-gate gap, story 013 / §21.3).
|
|
4
|
+
|
|
5
|
+
module Dinie
|
|
6
|
+
module Internal
|
|
7
|
+
# Pure, stateless redaction + truncation helpers. `module_function`: instance methods (so
|
|
8
|
+
# `self`-typing + internal calls resolve) plus singleton aliases for the two `RuntimeLogger`
|
|
9
|
+
# calls externally (`LogRedaction.redact_headers` / `.format_body`).
|
|
10
|
+
module LogRedaction
|
|
11
|
+
REDACTED: String
|
|
12
|
+
MAX_BODY_BYTES: Integer
|
|
13
|
+
REDACTED_HEADERS: Set[String]
|
|
14
|
+
REDACTED_BODY_FIELDS: Set[String]
|
|
15
|
+
NOT_JSON: untyped
|
|
16
|
+
|
|
17
|
+
# Replace the value of any sensitive header with the mask (case-insensitive).
|
|
18
|
+
def redact_headers: (untyped headers) -> Hash[String, untyped]
|
|
19
|
+
def self.redact_headers: (untyped headers) -> Hash[String, untyped]
|
|
20
|
+
|
|
21
|
+
# Deep-copy `value`, masking any Hash key (case-insensitive) that names a PII/secret field.
|
|
22
|
+
def redact_body: (untyped value) -> untyped
|
|
23
|
+
|
|
24
|
+
def redact_hash: (Hash[untyped, untyped] hash) -> Hash[untyped, untyped]
|
|
25
|
+
|
|
26
|
+
# Render a body for logging: redact PII, serialize to JSON, then truncate.
|
|
27
|
+
def format_body: (untyped body) -> String?
|
|
28
|
+
def self.format_body: (untyped body) -> String?
|
|
29
|
+
|
|
30
|
+
def serialize_for_log: (untyped body) -> String
|
|
31
|
+
def truncate_body: (String text) -> String
|
|
32
|
+
def clip_to_bytes: (String text, Integer max_bytes) -> String
|
|
33
|
+
def parse_json: (String text) -> untyped
|
|
34
|
+
def safe_generate: (untyped value) -> String
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Leveled logging facade with PII redaction. Constructed by `Middleware::Logging`.
|
|
38
|
+
class RuntimeLogger
|
|
39
|
+
LEVELS: Hash[Symbol, Integer]
|
|
40
|
+
ENV_VAR: String
|
|
41
|
+
|
|
42
|
+
attr_reader level: Symbol
|
|
43
|
+
|
|
44
|
+
def initialize: (?level: (Symbol | String)?, ?logger: untyped, ?env: String?) -> void
|
|
45
|
+
|
|
46
|
+
# Whether a call at `level` would emit under the configured level.
|
|
47
|
+
def enabled?: (Symbol level) -> bool
|
|
48
|
+
|
|
49
|
+
def error: (untyped message) -> void
|
|
50
|
+
def warn: (untyped message) -> void
|
|
51
|
+
def info: (untyped message) -> void
|
|
52
|
+
def debug: (untyped message) -> void
|
|
53
|
+
|
|
54
|
+
# Log an outgoing request at `debug` with redacted headers + body and the correlation triple.
|
|
55
|
+
def log_request: (method: (Symbol | String), url: String, headers: untyped, body: untyped, correlation: Hash[Symbol, untyped]) -> void
|
|
56
|
+
|
|
57
|
+
# Log an incoming response at `debug` with redacted headers + body, duration, and request id.
|
|
58
|
+
def log_response: (status: Integer, url: String, headers: untyped, body: untyped, duration_ms: Numeric, request_id: String?, correlation: Hash[Symbol, untyped]) -> void
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def emit: (Symbol level, untyped message) -> void
|
|
63
|
+
def emit_line: (String label, Hash[Symbol, untyped] fields, untyped headers, untyped body) -> void
|
|
64
|
+
def resolve_level: (untyped level, untyped env) -> Symbol
|
|
65
|
+
def valid_level?: (untyped value) -> bool
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
module Middleware
|
|
69
|
+
# Faraday response middleware — the logging hook point. `Faraday::Middleware` is untyped.
|
|
70
|
+
class Logging < Faraday::Middleware
|
|
71
|
+
ORIGIN_LOG_ID_KEY: Symbol
|
|
72
|
+
RETRY_COUNT_HEADER: String
|
|
73
|
+
REQUEST_ID_HEADER: String
|
|
74
|
+
|
|
75
|
+
def initialize: (untyped app, ?level: (Symbol | String)?, ?logger: untyped) -> void
|
|
76
|
+
|
|
77
|
+
def call: (untyped request_env) -> untyped
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def log_request: (untyped env, Hash[Symbol, untyped] correlation) -> void
|
|
82
|
+
def log_response: (untyped env, Hash[Symbol, untyped] correlation, Float started) -> void
|
|
83
|
+
def correlate: (untyped request_headers) -> Hash[Symbol, untyped]
|
|
84
|
+
def monotonic_now: () -> Float
|
|
85
|
+
def elapsed_ms: (Float started) -> Numeric
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Runtime model base + the `OMIT` sentinel (architecture §5.1, §6.2). Mirrors
|
|
2
|
+
# `lib/dinie/runtime/model.rb`.
|
|
3
|
+
|
|
4
|
+
module Dinie
|
|
5
|
+
module Internal
|
|
6
|
+
# The "argument not provided" sentinel (RB5). Compared by identity; exactly one frozen
|
|
7
|
+
# instance. Optional kwargs default to it and serializers drop any key still equal to it.
|
|
8
|
+
OMIT: Object
|
|
9
|
+
|
|
10
|
+
# Identity check for the OMIT sentinel.
|
|
11
|
+
def self.omitted?: (untyped value) -> bool
|
|
12
|
+
|
|
13
|
+
# Base class for every generated model: value-semantics POROs without `Data.define`
|
|
14
|
+
# (Ruby 3.1 floor). Subclasses declare fields with `attribute` (alphabetical, R-ORDER).
|
|
15
|
+
class Model
|
|
16
|
+
REDACTED_ATTRIBUTES: Array[Symbol]
|
|
17
|
+
|
|
18
|
+
# The declared attribute names, in declaration (R-ORDER) order.
|
|
19
|
+
def self.attributes: () -> Array[Symbol]
|
|
20
|
+
|
|
21
|
+
# Declare one or more attributes (defines an `attr_reader` for each; appends to `attributes`).
|
|
22
|
+
def self.attribute: (*Symbol | String names) -> void
|
|
23
|
+
|
|
24
|
+
# Carry the parent's attribute list into each subclass.
|
|
25
|
+
def self.inherited: (Class subclass) -> void
|
|
26
|
+
|
|
27
|
+
# Build a frozen instance from keyword arguments — one per declared attribute.
|
|
28
|
+
def initialize: (**untyped attrs) -> void
|
|
29
|
+
|
|
30
|
+
# Attributes in declaration (R-ORDER) order — deterministic.
|
|
31
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
32
|
+
alias to_hash to_h
|
|
33
|
+
|
|
34
|
+
# Enable pattern matching (`case model; in {status: "active"}`).
|
|
35
|
+
def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
36
|
+
|
|
37
|
+
# Value-equality: same class and same attribute values.
|
|
38
|
+
def ==: (untyped other) -> bool
|
|
39
|
+
alias eql? ==
|
|
40
|
+
|
|
41
|
+
def hash: () -> Integer
|
|
42
|
+
|
|
43
|
+
# Like `to_h`, but with PII redacted — safe for logs and the console.
|
|
44
|
+
def inspect: () -> String
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def validate_keys!: (Array[Symbol] expected, Hash[Symbol, untyped] attrs) -> void
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Transport wrapper for a `multipart/form-data` request body (architecture §10/§14).
|
|
2
|
+
# Mirrors `lib/dinie/runtime/multipart.rb`. Runtime-internal (the KYC upload seam).
|
|
3
|
+
|
|
4
|
+
module Dinie
|
|
5
|
+
module Internal
|
|
6
|
+
class Multipart
|
|
7
|
+
CONTENT_TYPE: String
|
|
8
|
+
DEFAULT_FILE_CONTENT_TYPE: String
|
|
9
|
+
DEFAULT_FILE_FILENAME: String
|
|
10
|
+
|
|
11
|
+
attr_reader fields: Hash[Symbol, String]
|
|
12
|
+
attr_reader file: untyped
|
|
13
|
+
|
|
14
|
+
def initialize: (fields: Hash[Symbol, String], ?file: untyped) -> void
|
|
15
|
+
|
|
16
|
+
# The Faraday multipart body: scalar fields plus the wrapped `file` part when present.
|
|
17
|
+
def to_faraday_body: () -> Hash[Symbol, untyped]
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def wrap_file: (untyped file) -> untyped
|
|
22
|
+
def multipart_part?: (untyped file) -> bool
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# `Dinie::Page` — one page of a cursor-paginated list + the auto-pagination engine
|
|
2
|
+
# (architecture §11, RB8). Mirrors `lib/dinie/runtime/paginator.rb`. Part of the public surface.
|
|
3
|
+
#
|
|
4
|
+
# `Page` is generic over its item type so `list*` returns `Page[Customer]`, etc. The item type is
|
|
5
|
+
# bound to `_Identifiable` (every list item responds to `#id` — the next page's cursor).
|
|
6
|
+
|
|
7
|
+
module Dinie
|
|
8
|
+
# The structural bound on a `Page`'s items: every paginated item carries an `id` (the cursor).
|
|
9
|
+
interface _Identifiable
|
|
10
|
+
def id: () -> String
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class Page[Elem < _Identifiable]
|
|
14
|
+
attr_reader data: Array[Elem]
|
|
15
|
+
attr_reader has_more: bool
|
|
16
|
+
|
|
17
|
+
NO_NEXT_PAGE_MESSAGE: String
|
|
18
|
+
UNSPECIFIED: untyped
|
|
19
|
+
|
|
20
|
+
# Build the FIRST page by invoking `fetch_page` with no cursor.
|
|
21
|
+
def self.from_fetch: [E < _Identifiable] (^(String?) -> Hash[Symbol, untyped] fetch_page) -> Page[E]
|
|
22
|
+
|
|
23
|
+
# Wrap a fetched `{ data:, has_more: }` envelope in a `Page`.
|
|
24
|
+
def self.build: [E < _Identifiable] (Hash[Symbol, untyped] envelope, ^(String?) -> Hash[Symbol, untyped] fetch_page) -> Page[E]
|
|
25
|
+
|
|
26
|
+
# A list endpoint is paginated iff its envelope carries `has_more`.
|
|
27
|
+
def self.paginated?: (untyped envelope) -> bool
|
|
28
|
+
|
|
29
|
+
def initialize: (data: Array[Elem], has_more: bool, fetch_page: ^(String?) -> Hash[Symbol, untyped]) -> void
|
|
30
|
+
|
|
31
|
+
# Whether a next page can be fetched.
|
|
32
|
+
def next_page?: () -> bool
|
|
33
|
+
|
|
34
|
+
# Fetch the next page (cursor = `id` of this page's last item). Guard with `next_page?`.
|
|
35
|
+
def next_page: () -> Page[Elem]
|
|
36
|
+
|
|
37
|
+
# Auto-paginate: yield every item of this page, then every following page. No block → `Enumerator`.
|
|
38
|
+
def each: () { (Elem item) -> void } -> self
|
|
39
|
+
| () -> Enumerator[Elem, self]
|
|
40
|
+
alias auto_paging_each each
|
|
41
|
+
|
|
42
|
+
# Yield page-by-page (manual control). No block → `Enumerator` over the pages.
|
|
43
|
+
def each_page: () { (Page[Elem] page) -> void } -> self
|
|
44
|
+
| () -> Enumerator[Page[Elem], self]
|
|
45
|
+
|
|
46
|
+
# The first `count` items across pages (or the very first item), fetched lazily. (`count`
|
|
47
|
+
# defaults to a private sentinel, so the signature is loose; returns `Elem?` or `Array[Elem]`.)
|
|
48
|
+
def first: (?untyped count) -> untyped
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Rate-limit snapshot + tracker (architecture §10, RB6). Mirrors `lib/dinie/runtime/rate_limit.rb`.
|
|
2
|
+
# `reset_at` is the SDK's only `Time` — every body timestamp stays an `Integer` epoch.
|
|
3
|
+
|
|
4
|
+
module Dinie
|
|
5
|
+
# The rate-limit snapshot read from the most recent response's `X-RateLimit-*` headers.
|
|
6
|
+
# Surfaced as `client.rate_limit`; `nil` until a response carries valid headers.
|
|
7
|
+
class RateLimit
|
|
8
|
+
attr_reader limit: Integer
|
|
9
|
+
attr_reader remaining: Integer
|
|
10
|
+
attr_reader reset_at: Time
|
|
11
|
+
|
|
12
|
+
def initialize: (limit: Integer, remaining: Integer, reset_at: Time) -> void
|
|
13
|
+
|
|
14
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
15
|
+
alias to_hash to_h
|
|
16
|
+
|
|
17
|
+
def deconstruct_keys: (Array[Symbol]? keys) -> Hash[Symbol, untyped]
|
|
18
|
+
|
|
19
|
+
def ==: (untyped other) -> bool
|
|
20
|
+
alias eql? ==
|
|
21
|
+
|
|
22
|
+
def hash: () -> Integer
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module Internal
|
|
26
|
+
# Parses the three `X-RateLimit-*` headers and holds the most recent snapshot for `HttpClient`.
|
|
27
|
+
class RateLimitTracker
|
|
28
|
+
LIMIT_HEADER: String
|
|
29
|
+
REMAINING_HEADER: String
|
|
30
|
+
RESET_HEADER: String
|
|
31
|
+
EPOCH_THRESHOLD_SECONDS: Integer
|
|
32
|
+
|
|
33
|
+
# Latest snapshot, or `nil` before any valid headers.
|
|
34
|
+
def snapshot: () -> Dinie::RateLimit?
|
|
35
|
+
|
|
36
|
+
# Fold a response's headers into the snapshot (a header-less/garbage response is a no-op).
|
|
37
|
+
def update: (untyped headers) -> void
|
|
38
|
+
|
|
39
|
+
# Parse the three headers into a `RateLimit`, or `nil` when any is absent/unparseable.
|
|
40
|
+
def self.parse: (untyped headers) -> Dinie::RateLimit?
|
|
41
|
+
def self.parse_count: (untyped raw) -> Integer?
|
|
42
|
+
def self.parse_reset: (untyped raw) -> Time?
|
|
43
|
+
def self.header_value: (untyped headers, String name) -> untyped
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Normalized per-call options, the trailing `request_options:` Hash (architecture §12, RB5).
|
|
2
|
+
# Mirrors `lib/dinie/runtime/request_options.rb`.
|
|
3
|
+
|
|
4
|
+
module Dinie
|
|
5
|
+
module Internal
|
|
6
|
+
class RequestOptions
|
|
7
|
+
attr_reader timeout: Numeric?
|
|
8
|
+
attr_reader idempotency_key: String?
|
|
9
|
+
attr_reader headers: Hash[String, String?]?
|
|
10
|
+
attr_reader max_retries: Integer?
|
|
11
|
+
|
|
12
|
+
# Pass a `RequestOptions` through, or build one from a Hash (string/symbol keys; `nil` → empty).
|
|
13
|
+
# Param is `untyped`: the body branches on `value.is_a?(self)`, which Steep cannot narrow on a
|
|
14
|
+
# union, so a precise union would mis-type the Hash branch.
|
|
15
|
+
def self.coerce: (untyped value) -> RequestOptions
|
|
16
|
+
|
|
17
|
+
def initialize: (?timeout: Numeric?, ?idempotency_key: String?, ?headers: Hash[untyped, untyped]?, ?max_retries: Integer?) -> void
|
|
18
|
+
|
|
19
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
20
|
+
alias to_hash to_h
|
|
21
|
+
|
|
22
|
+
def ==: (untyped other) -> bool
|
|
23
|
+
alias eql? ==
|
|
24
|
+
|
|
25
|
+
def hash: () -> Integer
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def validate_timeout: (untyped value) -> Numeric?
|
|
30
|
+
def validate_max_retries: (untyped value) -> Integer?
|
|
31
|
+
def validate_string: (untyped value, Symbol key) -> String?
|
|
32
|
+
def validate_headers: (untyped value) -> Hash[String, String?]?
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Retry policy — pure decision + delay functions (architecture §10, RB15). Mirrors
|
|
2
|
+
# `lib/dinie/runtime/retry.rb`. Runtime-internal: imported by `HttpClient`.
|
|
3
|
+
|
|
4
|
+
module Dinie
|
|
5
|
+
module Internal
|
|
6
|
+
module Retry
|
|
7
|
+
RETRYABLE_STATUS: Set[Integer]
|
|
8
|
+
INITIAL_BACKOFF_SECONDS: Float
|
|
9
|
+
MAX_BACKOFF_SECONDS: Integer
|
|
10
|
+
JITTER_RATIO: Float
|
|
11
|
+
RETRYABLE_NETWORK_ERRORS: Array[untyped]
|
|
12
|
+
|
|
13
|
+
# `module_function`: declared as instance methods (so `self`-typing is the module) plus
|
|
14
|
+
# singleton aliases (so `Retry.should_retry?` resolves at the `HttpClient` call sites).
|
|
15
|
+
|
|
16
|
+
# True only for the retryable status set (`{408, 429, 500, 502, 503, 504}`).
|
|
17
|
+
def should_retry?: (Integer status) -> bool
|
|
18
|
+
def self.should_retry?: (Integer status) -> bool
|
|
19
|
+
|
|
20
|
+
# Whether a thrown transport error (no HTTP response) is worth retrying (timeout/conn failure).
|
|
21
|
+
def retryable_network_error?: (Exception error) -> bool
|
|
22
|
+
def self.retryable_network_error?: (Exception error) -> bool
|
|
23
|
+
|
|
24
|
+
# Seconds to wait before the next attempt (Retry-After wins; else backoff minus jitter).
|
|
25
|
+
def retry_delay: (Integer attempt, ?retry_after: (String | Array[String])?, ?retry_after_ms: (String | Array[String])?) -> Float
|
|
26
|
+
def self.retry_delay: (Integer attempt, ?retry_after: (String | Array[String])?, ?retry_after_ms: (String | Array[String])?) -> Float
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# `TokenManager` — OAuth2 client_credentials token cache (architecture §10). Mirrors
|
|
2
|
+
# `lib/dinie/runtime/token_manager.rb`. Runtime-internal: built/injected by `Dinie::Client`.
|
|
3
|
+
# Faraday objects are `untyped` (no bundled RBS — informative-gate gap).
|
|
4
|
+
|
|
5
|
+
module Dinie
|
|
6
|
+
module Internal
|
|
7
|
+
class TokenManager
|
|
8
|
+
TOKEN_PATH: String
|
|
9
|
+
SESSION_EXCHANGE_PATH: String
|
|
10
|
+
REFRESH_MARGIN_SECONDS: Integer
|
|
11
|
+
GRANT_BODY: String
|
|
12
|
+
FORM_CONTENT_TYPE: String
|
|
13
|
+
MISSING_ACCESS_TOKEN: String
|
|
14
|
+
MISSING_EXPIRES_IN: String
|
|
15
|
+
|
|
16
|
+
def initialize: (client_id: String, client_secret: String, ?base_url: String?, ?connection: untyped, ?refresh_margin_seconds: Integer, ?adapter: Symbol?, ?clock: untyped, ?code: String?) -> void
|
|
17
|
+
|
|
18
|
+
# Return a valid Bearer access token, acquiring or refreshing transparently.
|
|
19
|
+
def access_token: () -> String
|
|
20
|
+
|
|
21
|
+
# Drop the cached token so the next `access_token` re-authenticates (the 401 one-shot seam).
|
|
22
|
+
def invalidate!: () -> void
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def token_valid?: () -> bool
|
|
27
|
+
def refresh_and_cache: () -> String
|
|
28
|
+
def fetch_token: () -> [ String, Numeric ]
|
|
29
|
+
def fetch_session_token: () -> [ String, Numeric ]
|
|
30
|
+
def fetch_partner_token: () -> [ String, Numeric ]
|
|
31
|
+
def fetch_client_credentials_token: () -> String
|
|
32
|
+
def exchange: (String cc_token, String code) -> [ String, Numeric ]
|
|
33
|
+
def request_exchange: (String cc_token, String code) -> untyped
|
|
34
|
+
def parse_exchange_response: (untyped raw_body) -> [ String, Numeric ]
|
|
35
|
+
def exchange_url: () -> String
|
|
36
|
+
def request_token: () -> untyped
|
|
37
|
+
def parse_token_response: (untyped raw_body) -> [ String, Numeric ]
|
|
38
|
+
def parse_json: (untyped raw_body) -> untyped
|
|
39
|
+
def valid_access_token?: (untyped value) -> bool
|
|
40
|
+
def valid_expires_in?: (untyped value) -> bool
|
|
41
|
+
def token_request_headers: () -> Hash[String, String]
|
|
42
|
+
def basic_credentials: () -> String
|
|
43
|
+
def token_url: () -> String
|
|
44
|
+
def success?: (Integer status) -> bool
|
|
45
|
+
def body_detail: (untyped response) -> String
|
|
46
|
+
def status_failure: (Integer status, String detail) -> String
|
|
47
|
+
def now: () -> Numeric
|
|
48
|
+
def build_connection: (Symbol? adapter) -> untyped
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# `Dinie::Webhooks.extract` — webhook verification + per-type deserialization (RB11, §8).
|
|
2
|
+
# Mirrors `lib/dinie/runtime/webhooks.rb`. `module_function`: methods are declared as instance
|
|
3
|
+
# methods (Steep types `self` as the module inside them) and are also callable on the module
|
|
4
|
+
# (`Dinie::Webhooks.extract`). Verification needs no client.
|
|
5
|
+
|
|
6
|
+
module Dinie
|
|
7
|
+
module Webhooks
|
|
8
|
+
DEFAULT_TOLERANCE_SECONDS: Integer
|
|
9
|
+
WHSEC_PREFIX: String
|
|
10
|
+
SIGNATURE_VERSION: String
|
|
11
|
+
|
|
12
|
+
# Verify a Standard Webhooks v1 payload and return the deserialized, typed event. Never returns
|
|
13
|
+
# an unverified event.
|
|
14
|
+
def extract: (headers: Hash[untyped, untyped], body: String, secret: (String | Array[String]), ?tolerance_seconds: Integer) -> Dinie::Events::WebhookEventBase
|
|
15
|
+
|
|
16
|
+
def signed_payload: (untyped webhook_id, untyped timestamp, String body) -> String
|
|
17
|
+
def required_header: (Hash[untyped, untyped] headers, String name, untyped error_class) -> untyped
|
|
18
|
+
def lookup_header: (Hash[untyped, untyped] headers, String name) -> untyped
|
|
19
|
+
def fetch_header: (Hash[untyped, untyped] headers, String name) -> untyped
|
|
20
|
+
def verify_timestamp!: (untyped timestamp, Integer tolerance_seconds) -> void
|
|
21
|
+
def verify_signature!: (String payload, (String | Array[String]) secret, String signature_header) -> void
|
|
22
|
+
def normalize_secrets: ((String | Array[String]) secret) -> Array[untyped]
|
|
23
|
+
def parse_signature_header: (String header) -> Array[untyped]
|
|
24
|
+
def signatures_match?: (String payload, Array[untyped] secrets, Array[untyped] provided_signatures) -> bool
|
|
25
|
+
def decode_secret: (String secret) -> untyped
|
|
26
|
+
def deserialize_verified_event: (String body) -> Dinie::Events::WebhookEventBase
|
|
27
|
+
|
|
28
|
+
# Module-function aliases (callable as `Dinie::Webhooks.extract`).
|
|
29
|
+
def self.extract: (headers: Hash[untyped, untyped], body: String, secret: (String | Array[String]), ?tolerance_seconds: Integer) -> Dinie::Events::WebhookEventBase
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# RBS mirror of the public surface (architecture §5.2, story 013). Hand-written in V0.3;
|
|
2
|
+
# emitted mechanically from the IR in V0.4. Doc-only — `steep check` consumes it; the gem
|
|
3
|
+
# ships it (gemspec `sig/**/*.rbs`) for consumers' own type checking. `.yardopts` excludes `sig/`.
|
|
4
|
+
|
|
5
|
+
module Dinie
|
|
6
|
+
VERSION: String
|
|
7
|
+
end
|