genesis_ruby 0.3.1 → 0.3.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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.kiro/specs/f2025112509-add_managed_recurring_api/.config.kiro +1 -0
  3. data/.kiro/specs/f2025112509-add_managed_recurring_api/design.md +332 -0
  4. data/.kiro/specs/f2025112509-add_managed_recurring_api/requirements.md +91 -0
  5. data/.kiro/specs/f2025112509-add_managed_recurring_api/tasks.md +139 -0
  6. data/.kiro/specs/f2025112603-add_reverify_endpoint_to_payee_account/.config.kiro +1 -0
  7. data/.kiro/specs/f2025112603-add_reverify_endpoint_to_payee_account/design.md +148 -0
  8. data/.kiro/specs/f2025112603-add_reverify_endpoint_to_payee_account/requirements.md +81 -0
  9. data/.kiro/specs/f2025112603-add_reverify_endpoint_to_payee_account/tasks.md +48 -0
  10. data/.kiro/specs/f2025112606-add_list_payees_trx_request/.config.kiro +1 -0
  11. data/.kiro/specs/f2025112606-add_list_payees_trx_request/design.md +112 -0
  12. data/.kiro/specs/f2025112606-add_list_payees_trx_request/requirements.md +74 -0
  13. data/.kiro/specs/f2025112606-add_list_payees_trx_request/tasks.md +38 -0
  14. data/.kiro/specs/f2025112609_update_payee_request_params/design.md +86 -0
  15. data/.kiro/specs/f2025112609_update_payee_request_params/requirements.md +86 -0
  16. data/.kiro/specs/f2025112609_update_payee_request_params/tasks.md +40 -0
  17. data/.kiro/specs/f2025112612-add_payee_owner_documents_and_verification_requests/.config.kiro +1 -0
  18. data/.kiro/specs/f2025112612-add_payee_owner_documents_and_verification_requests/design.md +246 -0
  19. data/.kiro/specs/f2025112612-add_payee_owner_documents_and_verification_requests/requirements.md +287 -0
  20. data/.kiro/specs/f2025112612-add_payee_owner_documents_and_verification_requests/tasks.md +76 -0
  21. data/.kiro/specs/f2025112614-add_money_transfer_payout_attributes_to_payout_rq/design.md +84 -0
  22. data/.kiro/specs/f2025112614-add_money_transfer_payout_attributes_to_payout_rq/requirements.md +88 -0
  23. data/.kiro/specs/f2025112614-add_money_transfer_payout_attributes_to_payout_rq/tasks.md +38 -0
  24. data/.kiro/steering/product.md +15 -0
  25. data/.kiro/steering/spec-folder-naming.md +16 -0
  26. data/.kiro/steering/structure.md +96 -0
  27. data/.kiro/steering/tech.md +66 -0
  28. data/CHANGELOG.md +23 -0
  29. data/Gemfile.lock +4 -4
  30. data/README.md +33 -0
  31. data/VERSION +1 -1
  32. data/lib/genesis_ruby/api/constants/non_financial/kyc/address_document_supported_types.rb +81 -0
  33. data/lib/genesis_ruby/api/constants/non_financial/payee/document_types.rb +57 -0
  34. data/lib/genesis_ruby/api/constants/non_financial/payee/owner_types.rb +30 -0
  35. data/lib/genesis_ruby/api/constants/transactions/parameters/money_transfer/purpose_of_payments.rb +50 -0
  36. data/lib/genesis_ruby/api/constants/transactions/parameters/money_transfer/sender_account_number_types.rb +50 -0
  37. data/lib/genesis_ruby/api/constants/transactions/parameters/money_transfer/source_of_funds.rb +44 -0
  38. data/lib/genesis_ruby/api/constants/transactions/parameters/money_transfer/types.rb +26 -0
  39. data/lib/genesis_ruby/api/constants/transactions/parameters/non_financial/billing_api/statement_response_fields.rb +37 -0
  40. data/lib/genesis_ruby/api/mixins/requests/financial/cards/mpi_attributes.rb +0 -10
  41. data/lib/genesis_ruby/api/mixins/requests/financial/money_transfer_payout_attributes.rb +131 -0
  42. data/lib/genesis_ruby/api/mixins/requests/non_financial/date_attributes.rb +87 -5
  43. data/lib/genesis_ruby/api/mixins/requests/non_financial/kyc/business_attributes.rb +42 -0
  44. data/lib/genesis_ruby/api/mixins/requests/non_financial/kyc/document_attributes.rb +8 -7
  45. data/lib/genesis_ruby/api/request.rb +15 -9
  46. data/lib/genesis_ruby/api/requests/base/non_financial/billing_api/base.rb +108 -0
  47. data/lib/genesis_ruby/api/requests/base/non_financial/payee/base.rb +54 -0
  48. data/lib/genesis_ruby/api/requests/financial/cards/authorize3d.rb +1 -3
  49. data/lib/genesis_ruby/api/requests/financial/cards/payout.rb +3 -1
  50. data/lib/genesis_ruby/api/requests/financial/cards/sale3d.rb +1 -3
  51. data/lib/genesis_ruby/api/requests/non_financial/billing_api/statement.rb +170 -0
  52. data/lib/genesis_ruby/api/requests/non_financial/billing_api/transactions.rb +20 -60
  53. data/lib/genesis_ruby/api/requests/non_financial/kyc/business/create.rb +45 -0
  54. data/lib/genesis_ruby/api/requests/non_financial/kyc/business/document.rb +60 -0
  55. data/lib/genesis_ruby/api/requests/non_financial/kyc/business/document_list.rb +59 -0
  56. data/lib/genesis_ruby/api/requests/non_financial/kyc/business/verification.rb +52 -0
  57. data/lib/genesis_ruby/api/requests/non_financial/kyc/verifications/address_by_document_proof.rb +92 -0
  58. data/lib/genesis_ruby/api/requests/non_financial/kyc/verifications/create.rb +4 -1
  59. data/lib/genesis_ruby/api/requests/non_financial/managed_recurring/cancel.rb +63 -0
  60. data/lib/genesis_ruby/api/requests/non_financial/managed_recurring/fetch.rb +63 -0
  61. data/lib/genesis_ruby/api/requests/non_financial/managed_recurring/fetch_all.rb +37 -0
  62. data/lib/genesis_ruby/api/requests/non_financial/payee/account/reverify.rb +61 -0
  63. data/lib/genesis_ruby/api/requests/non_financial/payee/associate_payee_with_owners.rb +105 -0
  64. data/lib/genesis_ruby/api/requests/non_financial/payee/create.rb +37 -7
  65. data/lib/genesis_ruby/api/requests/non_financial/payee/create_payee_document.rb +61 -0
  66. data/lib/genesis_ruby/api/requests/non_financial/payee/dissociate_payee_with_owners.rb +94 -0
  67. data/lib/genesis_ruby/api/requests/non_financial/payee/list.rb +38 -0
  68. data/lib/genesis_ruby/api/requests/non_financial/payee/list_payee_documents.rb +57 -0
  69. data/lib/genesis_ruby/api/requests/non_financial/payee/list_payee_owners.rb +70 -0
  70. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/associate_owner_with_owners.rb +109 -0
  71. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/create.rb +71 -0
  72. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/create_owner_document.rb +63 -0
  73. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/delete.rb +54 -0
  74. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/dissociate_owners.rb +96 -0
  75. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/list_owner_documents.rb +59 -0
  76. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/list_owners.rb +46 -0
  77. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/retrieve.rb +59 -0
  78. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/retrieve_owner_document.rb +62 -0
  79. data/lib/genesis_ruby/api/requests/non_financial/payee/owners/update.rb +66 -0
  80. data/lib/genesis_ruby/api/requests/non_financial/payee/retrieve_payee_document.rb +60 -0
  81. data/lib/genesis_ruby/api/requests/non_financial/payee/update.rb +34 -4
  82. data/lib/genesis_ruby/api/requests/non_financial/payee/verifications/create_payee_verification.rb +58 -0
  83. data/lib/genesis_ruby/api/requests/non_financial/payee/verifications/list_payee_verifications.rb +59 -0
  84. data/lib/genesis_ruby/api/requests/non_financial/payee/verifications/retrieve_payee_verification.rb +62 -0
  85. data/lib/genesis_ruby/api/requests/non_financial/tokenization/retokenize.rb +45 -0
  86. data/lib/genesis_ruby/api/requests/wpf/create.rb +19 -0
  87. data/lib/genesis_ruby/api/response.rb +15 -0
  88. data/lib/genesis_ruby/dependencies.rb +2 -0
  89. data/lib/genesis_ruby/network/adapter/net_http_adapter.rb +31 -5
  90. data/lib/genesis_ruby/network/base_network.rb +5 -0
  91. data/lib/genesis_ruby/network/net_http.rb +16 -4
  92. data/lib/genesis_ruby/utils/options/api_config.rb +43 -32
  93. data/lib/genesis_ruby/utils/options/network_adapter_config.rb +1 -1
  94. data/lib/genesis_ruby/version.rb +1 -1
  95. metadata +72 -3
@@ -0,0 +1,86 @@
1
+ # Requirements Document
2
+
3
+ ## Introduction
4
+
5
+ Update the existing Payee Create and Payee Update request classes in the genesis_ruby SDK to support the full set of request parameters defined in the current Payee API documentation. This includes adding `registration_number`, `date`, `notification_url`, and a nested `address` object with `city`, `street`, `state`, `country`, and `zip_code` fields. The obsolete flat address format and `neighborhood` field must not be emitted.
6
+
7
+ ## Glossary
8
+
9
+ - **SDK**: The genesis_ruby Ruby gem that wraps the emerchantpay payment gateway API
10
+ - **Payee_Create**: The `GenesisRuby::Api::Requests::NonFinancial::Payee::Create` class (POST /payee)
11
+ - **Payee_Update**: The `GenesisRuby::Api::Requests::NonFinancial::Payee::Update` class (PATCH /payee/:payee_unique_id)
12
+ - **Nested_Address**: A hash object under the `address` key containing `city`, `street`, `state`, `country`, `zip_code`
13
+ - **Deep_Compact**: The SDK's mechanism that removes nil values and empty hashes from the request structure before serialization
14
+
15
+ ## Requirements
16
+
17
+ ### Requirement 1: Payee Create — New Request Parameters
18
+
19
+ **User Story:** As a developer using the SDK, I want to set `registration_number`, `date`, `notification_url`, and nested address fields on Payee Create, so that the JSON payload matches the current Payee API documentation.
20
+
21
+ #### Acceptance Criteria
22
+
23
+ - [x] `payee_date` accessor is available and serialized as `payee.date`
24
+ - [x] `payee_notification_url` accessor is available and serialized as `payee.notification_url`
25
+ - [x] `payee_registration_number` accessor is available and serialized as `payee.registration_number`
26
+ - [x] `payee_address_city` is serialized under `payee.address.city`
27
+ - [x] `payee_address_street` is serialized under `payee.address.street`
28
+ - [x] `payee_address_state` is serialized under `payee.address.state`
29
+ - [x] `payee_address_country` is serialized under `payee.address.country`
30
+ - [x] `payee_address_zip_code` is serialized under `payee.address.zip_code`
31
+ - [x] `payee_address_country` is validated against the ISO country list (optional field)
32
+ - [x] When all address fields are nil, the `address` key is not emitted in the payload
33
+ - [x] The `neighborhood` field is never emitted
34
+ - [x] Existing required fields (`payee_type`, `payee_name`, `payee_country`) remain unchanged
35
+ - [x] All new fields are optional
36
+
37
+ ### Requirement 2: Payee Update — New Request Parameters
38
+
39
+ **User Story:** As a developer using the SDK, I want to set `registration_number`, `date`, `notification_url`, and nested address fields on Payee Update, so that the JSON payload matches the current Payee API documentation.
40
+
41
+ #### Acceptance Criteria
42
+
43
+ - [x] `payee_date` accessor is available and serialized as `payee.date`
44
+ - [x] `payee_notification_url` accessor is available and serialized as `payee.notification_url`
45
+ - [x] `payee_registration_number` accessor is available and serialized as `payee.registration_number`
46
+ - [x] `payee_address_city` is serialized under `payee.address.city`
47
+ - [x] `payee_address_street` is serialized under `payee.address.street`
48
+ - [x] `payee_address_state` is serialized under `payee.address.state`
49
+ - [x] `payee_address_country` is serialized under `payee.address.country`
50
+ - [x] `payee_address_zip_code` is serialized under `payee.address.zip_code`
51
+ - [x] `payee_address_country` is validated against the ISO country list (optional field)
52
+ - [x] When all address fields are nil, the `address` key is not emitted in the payload
53
+ - [x] The `neighborhood` field is never emitted
54
+ - [x] HTTP method remains PATCH
55
+ - [x] Only `payee_unique_id` is required; all other fields are optional
56
+ - [x] All new fields are optional
57
+
58
+ ### Requirement 3: No Obsolete Fields
59
+
60
+ **User Story:** As a developer using the SDK, I want the Payee requests to not emit obsolete fields, so that the payload is compliant with the current API.
61
+
62
+ #### Acceptance Criteria
63
+
64
+ - [x] No `neighborhood` field is present in any request structure
65
+ - [x] No flat `address` string field (e.g., `payee.address = "123 Main St"`) is used
66
+ - [x] No flat `zip_code` field at the payee root level is used
67
+
68
+ ### Requirement 4: Test Coverage
69
+
70
+ **User Story:** As a developer, I want RSpec tests covering all new parameters, so that regressions are caught.
71
+
72
+ #### Acceptance Criteria
73
+
74
+ - [x] Spec for Payee Create verifies full request structure including nested address
75
+ - [x] Spec for Payee Create verifies address is omitted when all address fields are nil
76
+ - [x] Spec for Payee Create verifies no `neighborhood` in address
77
+ - [x] Spec for Payee Create verifies `registration_number` serialization
78
+ - [x] Spec for Payee Create verifies `payee_address_country` validation
79
+ - [x] Spec for Payee Update verifies full request structure including nested address
80
+ - [x] Spec for Payee Update verifies address is omitted when all address fields are nil
81
+ - [x] Spec for Payee Update verifies no `neighborhood` in address
82
+ - [x] Spec for Payee Update verifies `registration_number` serialization
83
+ - [x] Spec for Payee Update verifies `payee_address_country` validation
84
+ - [x] Spec for Payee Update verifies minimum request data (only `payee_unique_id` required)
85
+ - [x] All existing tests continue to pass
86
+ - [x] `bundle exec rake styles` passes with 0 offenses
@@ -0,0 +1,40 @@
1
+ # Tasks
2
+
3
+ ## Task 1: Add new fields to Payee Create request class
4
+
5
+ - [x] Add `attr_accessor` for `payee_date`, `payee_notification_url`, `payee_registration_number`
6
+ - [x] Add `attr_accessor` for `payee_address_city`, `payee_address_street`, `payee_address_state`, `payee_address_country`, `payee_address_zip_code`
7
+ - [x] Add `payee_address_country` to `field_values` for ISO validation
8
+ - [x] Update `request_structure` to include new fields and nested `address`
9
+ - [x] Add private `payee_address_structure` method
10
+
11
+ ## Task 2: Add new fields to Payee Update request class
12
+
13
+ - [x] Add `attr_accessor` for `payee_date`, `payee_notification_url`, `payee_registration_number`
14
+ - [x] Add `attr_accessor` for `payee_address_city`, `payee_address_street`, `payee_address_state`, `payee_address_country`, `payee_address_zip_code`
15
+ - [x] Add `payee_address_country` to `field_values` for ISO validation
16
+ - [x] Update `request_structure` to include new fields and nested `address`
17
+ - [x] Add private `payee_address_structure` method
18
+
19
+ ## Task 3: Update Payee Create spec
20
+
21
+ - [x] Add new fields to `sample_data` and `request` let blocks
22
+ - [x] Update structure assertion to include all new fields
23
+ - [x] Add context for nested address serialization (present, absent, no neighborhood)
24
+ - [x] Add context for `registration_number`
25
+ - [x] Add test for `payee_address_country` validation
26
+
27
+ ## Task 4: Update Payee Update spec
28
+
29
+ - [x] Add new fields to `sample_data` and `request` let blocks
30
+ - [x] Update structure assertion to include all new fields
31
+ - [x] Add context for nested address serialization (present, absent, no neighborhood)
32
+ - [x] Add context for `registration_number`
33
+ - [x] Add test for `payee_address_country` validation
34
+ - [x] Update minimum request data test to nil all new fields
35
+
36
+ ## Task 5: Validation
37
+
38
+ - [x] `bundle exec rake test` — 7089 examples, 0 failures
39
+ - [x] `bundle exec rake styles` — 933 files inspected, no offenses detected
40
+ - [x] `git diff --stat` shows only 4 modified files (create.rb, update.rb, create_spec.rb, update_spec.rb)
@@ -0,0 +1 @@
1
+ {"specId": "e7536868-191d-4a23-aacb-b036ee65c0bb", "workflowType": "requirements-first", "specType": "feature"}
@@ -0,0 +1,246 @@
1
+ # Design Document: Payee Owner, Documents & Verifications
2
+
3
+ ## Overview
4
+
5
+ Extend the genesis_ruby SDK with 20 new non-financial request classes for the Payee API covering Owner management, Document management, and Verification management. Additionally, add HTTP DELETE method infrastructure since the existing codebase only supports POST, GET, PUT, and PATCH.
6
+
7
+ All new request classes follow the established `Base::Versioned` pattern: JSON format, versioned API paths, `attr_accessor` parameters, field validations, request structure hashes, and path placeholder replacement in `process_request_parameters`.
8
+
9
+ ## Architecture
10
+
11
+ The new classes follow the PHP SDK's flat layout — Payee-level operations (documents, owners association) sit directly in the `Payee` module, Owner CRUD and Owner sub-operations go in `Payee::Owners`, and Verifications in `Payee::Verifications`:
12
+
13
+ ```
14
+ lib/genesis_ruby/api/requests/non_financial/payee/
15
+ ├── Account/ (existing)
16
+ │ ├── create.rb, retrieve.rb, update.rb, list.rb
17
+ ├── Owners/ (Owner CRUD + Owner sub-operations)
18
+ │ ├── create.rb (POST /payee/owners)
19
+ │ ├── retrieve.rb (GET /payee/owners/:owner_unique_id)
20
+ │ ├── update.rb (PATCH /payee/owners/:owner_unique_id)
21
+ │ ├── delete.rb (DELETE /payee/owners/:owner_unique_id)
22
+ │ ├── list_owners.rb (GET /payee/owners)
23
+ │ ├── associate_owner_with_owners.rb (POST /payee/owners/:owner_unique_id/owners)
24
+ │ ├── dissociate_owners.rb (DELETE /payee/owners/:owner_unique_id/owners)
25
+ │ ├── create_owner_document.rb (POST /payee/owners/:owner_unique_id/documents)
26
+ │ ├── retrieve_owner_document.rb (GET /payee/owners/:owner_unique_id/documents/:document_unique_id)
27
+ │ └── list_owner_documents.rb (GET /payee/owners/:owner_unique_id/documents)
28
+ ├── Verifications/
29
+ │ ├── create_payee_verification.rb (POST /payee/:payee_unique_id/verifications)
30
+ │ ├── retrieve_payee_verification.rb (GET /payee/:payee_unique_id/verifications/:verification_unique_id)
31
+ │ └── list_payee_verifications.rb (GET /payee/:payee_unique_id/verifications)
32
+ ├── create.rb, retrieve.rb, update.rb (existing Payee CRUD)
33
+ ├── list_payees.rb (GET /payee)
34
+ ├── list_payee_owners.rb (GET /payee/:payee_unique_id/owners)
35
+ ├── associate_payee_with_owners.rb (POST /payee/:payee_unique_id/owners)
36
+ ├── dissociate_payee_with_owners.rb (DELETE /payee/:payee_unique_id/owners)
37
+ ├── create_payee_document.rb (POST /payee/:payee_unique_id/documents)
38
+ ├── retrieve_payee_document.rb (GET /payee/:payee_unique_id/documents/:document_unique_id)
39
+ └── list_payee_documents.rb (GET /payee/:payee_unique_id/documents)
40
+ ```
41
+
42
+ Infrastructure changes for DELETE support:
43
+
44
+ ```
45
+ Api::Request → METHOD_DELETE constant + init_delete_configuration method
46
+ Utils::Options::ApiConfig → load_delete_config method
47
+ Network::Adapter::NetHttpAdapter → DELETE case in execute
48
+ Utils::Options::NetworkAdapterConfig → DELETE format in fetch_content_type
49
+ ```
50
+
51
+ ## Components and Interfaces
52
+
53
+ ### 1. HTTP DELETE Infrastructure
54
+
55
+ **`Api::Request`** — Add `METHOD_DELETE = 'DELETE'` constant and `init_delete_configuration` method that delegates to `@api_config.load_delete_config`.
56
+
57
+ **`Utils::Options::ApiConfig`** — Add `load_delete_config` method:
58
+ ```ruby
59
+ def load_delete_config
60
+ self.protocol = GenesisRuby::Api::Request::PROTOCOL_HTTPS
61
+ self.port = GenesisRuby::Api::Request::PORT_HTTPS
62
+ self.type = GenesisRuby::Api::Request::METHOD_DELETE
63
+ self.format = Builder::JSON
64
+ self.parser_skip_root_node = false
65
+ self.authorization = GenesisRuby::Api::Request::AUTH_TYPE_BASIC
66
+ self.bearer_token = nil
67
+ end
68
+ ```
69
+
70
+ **`Network::Adapter::NetHttpAdapter`** — Add DELETE case in `execute`:
71
+ ```ruby
72
+ when Api::Request::METHOD_DELETE then @response = @request.delete path, headers
73
+ ```
74
+ Note: DELETE requests send headers only (no body), similar to GET. The `headers` method should exclude payload headers for DELETE, same as GET.
75
+
76
+ **`Utils::Options::NetworkAdapterConfig`** — Add `Builder::JSON` handling for DELETE in `fetch_content_type`. Since DELETE uses `Builder::JSON` format, it's already handled by the existing `when Builder::JSON then 'application/json'` case. No change needed here.
77
+
78
+ ### 2. Request Class Patterns
79
+
80
+ All 20 request classes follow one of four patterns:
81
+
82
+ **GET (Retrieve)** — `init_get_configuration` in `init_configuration`, empty `request_structure`, placeholder replacement in `process_request_parameters`.
83
+
84
+ **GET (List)** — Same as Retrieve, plus optional query parameter building appended to the URL.
85
+
86
+ **POST (Create/Associate)** — Default POST, `request_structure` returns the JSON body hash, placeholder replacement.
87
+
88
+ **PATCH (Update)** — `init_patch_configuration` in constructor, `request_structure` returns updatable fields, placeholder replacement.
89
+
90
+ **DELETE (Dissociate/Delete)** — `init_delete_configuration` in constructor, `request_structure` returns body (for dissociate) or empty hash (for delete), placeholder replacement.
91
+
92
+ ### 3. Constants Module
93
+
94
+ **`Api::Constants::NonFinancial::Payee::OwnerTypes`**:
95
+ ```ruby
96
+ COMPANY = 'company'
97
+ PERSON = 'person'
98
+ DIRECTOR = 'director'
99
+ ULTIMATE_BENEFICIAL_OWNER = 'ultimate_beneficial_owner'
100
+ ```
101
+
102
+ **`Api::Constants::NonFinancial::Payee::DocumentTypes`**:
103
+ ```ruby
104
+ POI = 'poi'
105
+ PASSPORT = 'passport'
106
+ ID_CARD = 'id_card'
107
+ DRIVING_LICENSE = 'driving_license'
108
+ POA = 'poa'
109
+ UTILITY_BILL = 'utility_bill'
110
+ BANK_STATEMENT = 'bank_statement'
111
+ COMPANY_REGISTRATION = 'company_registration'
112
+ TAX_RETURN = 'tax_return'
113
+ MEMORANDUM_OF_ASSOCIATION = 'memorandum_of_association'
114
+ SHAREHOLDER_REGISTER = 'shareholder_register'
115
+ BOARD_RESOLUTION = 'board_resolution'
116
+ PROOF_OF_ADDRESS = 'proof_of_address'
117
+ ```
118
+
119
+ ## Data Models
120
+
121
+ ### Request Parameters by Class
122
+
123
+ | Class | Required Fields | Optional Fields | Validated Fields |
124
+ |-------|----------------|-----------------|------------------|
125
+ | ListPayeeOwners | payee_unique_id | type (query param) | — |
126
+ | AssociatePayeeWithOwners | payee_unique_id | owners[] | — |
127
+ | DissociatePayeeWithOwners | payee_unique_id | owners[] | — |
128
+ | CreatePayeeDocument | payee_unique_id, document_type, file | — | document_type |
129
+ | RetrievePayeeDocument | payee_unique_id, document_unique_id | — | — |
130
+ | ListPayeeDocuments | payee_unique_id | — | — |
131
+ | Verifications::CreatePayeeVerification | payee_unique_id | notification_url, redirect_url, with_checks_retry | — |
132
+ | Verifications::RetrievePayeeVerification | payee_unique_id, verification_unique_id | — | — |
133
+ | Verifications::ListPayeeVerifications | payee_unique_id | — | — |
134
+ | Owners::Create | owner_type, owner_name, owner_country | owner_date, notification_url, registration_number, owner_address{}, payees[], owners[] | owner_type, owner_country |
135
+ | Owners::Retrieve | owner_unique_id | — | — |
136
+ | Owners::Update | owner_unique_id | owner_name, owner_country, owner_date, notification_url, registration_number, owner_address{} | owner_country |
137
+ | Owners::Delete | owner_unique_id | — | — |
138
+ | Owners::ListOwners | — | — | — |
139
+ | Owners::AssociateOwnerWithOwners | owner_unique_id | owners[] | — |
140
+ | Owners::DissociateOwners | owner_unique_id | owners[] | — |
141
+ | Owners::CreateOwnerDocument | owner_unique_id, document_type, file | — | document_type |
142
+ | Owners::RetrieveOwnerDocument | owner_unique_id, document_unique_id | — | — |
143
+ | Owners::ListOwnerDocuments | owner_unique_id | — | — |
144
+
145
+ ### URL Patterns
146
+
147
+ | Class | HTTP Method | URL Pattern |
148
+ |-------|------------|-------------|
149
+ | ListPayeeOwners | GET | `payee/:payee_unique_id/owners[?type=X]` |
150
+ | AssociatePayeeWithOwners | POST | `payee/:payee_unique_id/owners` |
151
+ | DissociatePayeeWithOwners | DELETE | `payee/:payee_unique_id/owners` |
152
+ | CreatePayeeDocument | POST | `payee/:payee_unique_id/documents` |
153
+ | RetrievePayeeDocument | GET | `payee/:payee_unique_id/documents/:document_unique_id` |
154
+ | ListPayeeDocuments | GET | `payee/:payee_unique_id/documents` |
155
+ | Verifications::CreatePayeeVerification | POST | `payee/:payee_unique_id/verifications` |
156
+ | Verifications::RetrievePayeeVerification | GET | `payee/:payee_unique_id/verifications/:verification_unique_id` |
157
+ | Verifications::ListPayeeVerifications | GET | `payee/:payee_unique_id/verifications` |
158
+ | Owners::Create | POST | `payee/owners` |
159
+ | Owners::Retrieve | GET | `payee/owners/:owner_unique_id` |
160
+ | Owners::Update | PATCH | `payee/owners/:owner_unique_id` |
161
+ | Owners::Delete | DELETE | `payee/owners/:owner_unique_id` |
162
+ | Owners::ListOwners | GET | `payee/owners` |
163
+ | Owners::AssociateOwnerWithOwners | POST | `payee/owners/:owner_unique_id/owners` |
164
+ | Owners::DissociateOwners | DELETE | `payee/owners/:owner_unique_id/owners` |
165
+ | Owners::CreateOwnerDocument | POST | `payee/owners/:owner_unique_id/documents` |
166
+ | Owners::RetrieveOwnerDocument | GET | `payee/owners/:owner_unique_id/documents/:document_unique_id` |
167
+ | Owners::ListOwnerDocuments | GET | `payee/owners/:owner_unique_id/documents` |
168
+
169
+
170
+ ## Correctness Properties
171
+
172
+ *A property is a characteristic or behavior that should hold true across all valid executions of a system — essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
173
+
174
+ ### Property 1: Required field validation rejects nil values
175
+
176
+ *For any* request class and *for any* field declared in `required_fields`, setting that field to `nil` and calling `build_document` SHALL raise a `ParameterError`.
177
+
178
+ **Validates: Requirements 2.3, 3.3, 4.3, 5.3, 6.3, 7.3, 8.3, 9.3, 10.3, 11.3, 12.3, 13.3, 14.3, 16.3, 17.3, 18.3, 19.3, 20.3**
179
+
180
+ ### Property 2: Path placeholder replacement produces valid URLs
181
+
182
+ *For any* request class with path placeholders and *for any* valid non-empty ID string, after calling `build_document`, the resulting URL SHALL contain the ID string and SHALL NOT contain any `:placeholder` tokens.
183
+
184
+ **Validates: Requirements 2.6, 3.6, 4.6, 5.6, 6.5, 7.5, 8.6, 9.5, 10.5, 12.5, 13.7, 14.5, 16.6, 17.6, 18.6, 19.5, 20.5, 21.3**
185
+
186
+ ### Property 3: Field value validation rejects invalid enum values
187
+
188
+ *For any* request class with `field_values` constraints (owner_type, document_type, country) and *for any* string not in the allowed values list, calling `build_document` SHALL raise a `ParameterError`.
189
+
190
+ **Validates: Requirements 5.4, 11.4, 11.5, 13.5, 18.4, 21.6**
191
+
192
+ ### Property 4: Request structure serialization preserves input data
193
+
194
+ *For any* POST/PATCH/DELETE request class with a non-empty body and *for any* set of valid input parameters, the JSON-parsed output of `build_document` SHALL contain all non-nil input values under the correct nesting keys.
195
+
196
+ **Validates: Requirements 3.4, 3.5, 4.4, 4.5, 5.5, 8.5, 11.7, 13.6, 16.4, 16.5, 17.4, 17.5, 18.5**
197
+
198
+ ### Property 5: Query parameter URL building for list endpoints
199
+
200
+ *For any* list request class with optional query parameters and *for any* non-nil query parameter value, the resulting URL after `build_document` SHALL contain the parameter as a properly encoded query string. When all query parameters are nil, the URL SHALL NOT contain a `?`.
201
+
202
+ **Validates: Requirements 2.4, 21.5**
203
+
204
+ ## Error Handling
205
+
206
+ All request classes use the existing `Base::Versioned` validation framework:
207
+
208
+ - **`ParameterError`** — Raised when required fields are nil/empty or field values don't match allowed lists. Raised during `build_document` → `process_request_parameters` → `check_requirements` → `validate`.
209
+ - **`InvalidArgumentError`** — Raised for invalid API versions or builder interface mismatches.
210
+ - **`BuilderError`** — Raised if the builder interface cannot be configured.
211
+ - **`NetworkError`** — Raised by the network adapter for connection failures, timeouts, or invalid request types (including unrecognized HTTP methods).
212
+
213
+ No new error types are needed. The DELETE infrastructure follows the same error patterns as existing methods.
214
+
215
+ ## Testing Strategy
216
+
217
+ ### Unit Tests (RSpec)
218
+
219
+ Each of the 20 request classes gets a corresponding `_spec.rb` file following the existing pattern:
220
+
221
+ 1. **Config setup** — Standard `let(:config)` with username, password, token, endpoint, environment.
222
+ 2. **Sample data** — `let(:sample_data)` with Faker-generated values for all parameters.
223
+ 3. **Request setup** — `let(:request)` that creates and populates the request instance.
224
+ 4. **Structure test** — Verify `JSON.parse(request.build_document)` matches expected structure.
225
+ 5. **URL test** — Verify `request.api_config['url']` contains the correct path with replaced placeholders.
226
+ 6. **HTTP method test** — Verify `request.api_config['type']` matches expected method (GET/POST/PATCH/DELETE).
227
+ 7. **Token test** — Verify `request.api_config['token']` is nil (include_token: false).
228
+ 8. **Validation tests** — Required fields nil → ParameterError, invalid field values → ParameterError.
229
+ 9. **Shared examples** — `include_examples 'base request examples'` and `include_examples 'versioned request examples'`.
230
+
231
+ Infrastructure tests:
232
+ - `Api::Request` — Verify `METHOD_DELETE` constant and `init_delete_configuration` method.
233
+ - `Utils::Options::ApiConfig` — Verify `load_delete_config` sets correct attributes.
234
+ - `Network::Adapter::NetHttpAdapter` — Verify DELETE requests are dispatched correctly.
235
+
236
+ ### Property-Based Tests
237
+
238
+ Using the `rspec-property` or `rantly` gem, minimum 100 iterations per property:
239
+
240
+ - **Property 1**: Generate random request classes and nil out each required field, verify ParameterError.
241
+ - **Property 2**: Generate random UUID strings for ID fields, verify URL contains them and has no placeholders.
242
+ - **Property 3**: Generate random invalid strings for enum fields, verify ParameterError.
243
+ - **Property 4**: Generate random valid parameter sets, verify JSON output contains all values.
244
+ - **Property 5**: Generate random query param values, verify URL encoding.
245
+
246
+ Each property test tagged with: `# Feature: payee-owner-documents-verifications, Property N: <title>`