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.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +12 -0
  3. data/LICENSE +21 -0
  4. data/README.md +280 -0
  5. data/lib/dinie/generated/api_version.rb +8 -0
  6. data/lib/dinie/generated/client.rb +96 -0
  7. data/lib/dinie/generated/errors/registry.rb +40 -0
  8. data/lib/dinie/generated/events/base.rb +11 -0
  9. data/lib/dinie/generated/events/credit_offer.rb +56 -0
  10. data/lib/dinie/generated/events/customer_created.rb +42 -0
  11. data/lib/dinie/generated/events/customer_denied.rb +39 -0
  12. data/lib/dinie/generated/events/customer_kyc_updated.rb +36 -0
  13. data/lib/dinie/generated/events/customer_status.rb +48 -0
  14. data/lib/dinie/generated/events/deserializers.rb +35 -0
  15. data/lib/dinie/generated/events/loan_active.rb +35 -0
  16. data/lib/dinie/generated/events/loan_created.rb +38 -0
  17. data/lib/dinie/generated/events/loan_payment_received.rb +46 -0
  18. data/lib/dinie/generated/events/loan_processing.rb +37 -0
  19. data/lib/dinie/generated/events/loan_signature_received.rb +48 -0
  20. data/lib/dinie/generated/events/loan_status.rb +73 -0
  21. data/lib/dinie/generated/events.rb +4 -0
  22. data/lib/dinie/generated/resources/banks.rb +25 -0
  23. data/lib/dinie/generated/resources/biometrics.rb +27 -0
  24. data/lib/dinie/generated/resources/credentials.rb +56 -0
  25. data/lib/dinie/generated/resources/credit_offers.rb +59 -0
  26. data/lib/dinie/generated/resources/customers.rb +200 -0
  27. data/lib/dinie/generated/resources/loans.rb +70 -0
  28. data/lib/dinie/generated/resources/webhook_endpoints.rb +97 -0
  29. data/lib/dinie/generated/resources.rb +9 -0
  30. data/lib/dinie/generated/types/bank.rb +17 -0
  31. data/lib/dinie/generated/types/biometrics_session.rb +16 -0
  32. data/lib/dinie/generated/types/biometrics_session_exchange_response.rb +23 -0
  33. data/lib/dinie/generated/types/credential.rb +50 -0
  34. data/lib/dinie/generated/types/credit_offer.rb +62 -0
  35. data/lib/dinie/generated/types/customer.rb +45 -0
  36. data/lib/dinie/generated/types/customer_bank_account.rb +33 -0
  37. data/lib/dinie/generated/types/ids.rb +18 -0
  38. data/lib/dinie/generated/types/kyc.rb +458 -0
  39. data/lib/dinie/generated/types/kyc_attachment_response.rb +16 -0
  40. data/lib/dinie/generated/types/loan.rb +51 -0
  41. data/lib/dinie/generated/types/money.rb +4 -0
  42. data/lib/dinie/generated/types/simulation.rb +35 -0
  43. data/lib/dinie/generated/types/transaction.rb +43 -0
  44. data/lib/dinie/generated/types/webhook_endpoint.rb +52 -0
  45. data/lib/dinie/generated/types/webhook_secret_rotation.rb +17 -0
  46. data/lib/dinie/generated/types.rb +18 -0
  47. data/lib/dinie/runtime/errors.rb +295 -0
  48. data/lib/dinie/runtime/http.rb +325 -0
  49. data/lib/dinie/runtime/idempotency.rb +34 -0
  50. data/lib/dinie/runtime/logger.rb +326 -0
  51. data/lib/dinie/runtime/model.rb +162 -0
  52. data/lib/dinie/runtime/multipart.rb +77 -0
  53. data/lib/dinie/runtime/paginator.rb +164 -0
  54. data/lib/dinie/runtime/rate_limit.rb +150 -0
  55. data/lib/dinie/runtime/request_options.rb +112 -0
  56. data/lib/dinie/runtime/retry.rb +74 -0
  57. data/lib/dinie/runtime/token_manager.rb +341 -0
  58. data/lib/dinie/runtime/webhooks.rb +194 -0
  59. data/lib/dinie/version.rb +7 -0
  60. data/lib/dinie.rb +36 -0
  61. data/sig/_external/faraday.rbs +44 -0
  62. data/sig/dinie/generated/client.rbs +45 -0
  63. data/sig/dinie/generated/errors/registry.rbs +40 -0
  64. data/sig/dinie/generated/events/base.rbs +17 -0
  65. data/sig/dinie/generated/events/credit_offer.rbs +33 -0
  66. data/sig/dinie/generated/events/customer_created.rbs +27 -0
  67. data/sig/dinie/generated/events/customer_denied.rbs +25 -0
  68. data/sig/dinie/generated/events/customer_kyc_updated.rbs +21 -0
  69. data/sig/dinie/generated/events/customer_status.rbs +26 -0
  70. data/sig/dinie/generated/events/deserializers.rbs +9 -0
  71. data/sig/dinie/generated/events/loan_active.rbs +20 -0
  72. data/sig/dinie/generated/events/loan_created.rbs +23 -0
  73. data/sig/dinie/generated/events/loan_payment_received.rbs +28 -0
  74. data/sig/dinie/generated/events/loan_processing.rbs +23 -0
  75. data/sig/dinie/generated/events/loan_signature_received.rbs +30 -0
  76. data/sig/dinie/generated/events/loan_status.rbs +40 -0
  77. data/sig/dinie/generated/resources/banks.rbs +15 -0
  78. data/sig/dinie/generated/resources/credentials.rbs +21 -0
  79. data/sig/dinie/generated/resources/credit_offers.rbs +19 -0
  80. data/sig/dinie/generated/resources/customers.rbs +58 -0
  81. data/sig/dinie/generated/resources/loans.rbs +26 -0
  82. data/sig/dinie/generated/resources/webhook_endpoints.rbs +35 -0
  83. data/sig/dinie/generated/types/bank.rbs +12 -0
  84. data/sig/dinie/generated/types/biometrics_session.rbs +11 -0
  85. data/sig/dinie/generated/types/credential.rbs +26 -0
  86. data/sig/dinie/generated/types/credit_offer.rbs +24 -0
  87. data/sig/dinie/generated/types/customer.rbs +25 -0
  88. data/sig/dinie/generated/types/customer_bank_account.rbs +26 -0
  89. data/sig/dinie/generated/types/enums.rbs +66 -0
  90. data/sig/dinie/generated/types/ids.rbs +21 -0
  91. data/sig/dinie/generated/types/kyc/attachment.rbs +14 -0
  92. data/sig/dinie/generated/types/kyc/common.rbs +42 -0
  93. data/sig/dinie/generated/types/kyc/requirements.rbs +117 -0
  94. data/sig/dinie/generated/types/kyc/submitted.rbs +21 -0
  95. data/sig/dinie/generated/types/kyc/uploads.rbs +24 -0
  96. data/sig/dinie/generated/types/loan.rbs +32 -0
  97. data/sig/dinie/generated/types/money.rbs +6 -0
  98. data/sig/dinie/generated/types/simulation.rbs +28 -0
  99. data/sig/dinie/generated/types/transaction.rbs +24 -0
  100. data/sig/dinie/generated/types/webhook_endpoint.rbs +38 -0
  101. data/sig/dinie/runtime/errors.rbs +106 -0
  102. data/sig/dinie/runtime/http.rbs +59 -0
  103. data/sig/dinie/runtime/idempotency.rbs +15 -0
  104. data/sig/dinie/runtime/logger.rbs +89 -0
  105. data/sig/dinie/runtime/model.rbs +51 -0
  106. data/sig/dinie/runtime/multipart.rbs +25 -0
  107. data/sig/dinie/runtime/paginator.rbs +50 -0
  108. data/sig/dinie/runtime/rate_limit.rbs +46 -0
  109. data/sig/dinie/runtime/request_options.rbs +35 -0
  110. data/sig/dinie/runtime/retry.rbs +29 -0
  111. data/sig/dinie/runtime/token_manager.rbs +51 -0
  112. data/sig/dinie/runtime/webhooks.rbs +31 -0
  113. data/sig/dinie/version.rbs +7 -0
  114. 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