airwallex 0.2.0 → 0.3.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.
@@ -1,389 +0,0 @@
1
- # Sprint 1 Implementation Plan
2
-
3
- ## Overview
4
-
5
- Sprint 1 focuses on establishing the foundational architecture of the Airwallex Ruby gem, including core infrastructure, authentication mechanisms, and basic API communication capabilities. This sprint prioritizes correctness, idempotency, and type safety as outlined in the architectural blueprint.
6
-
7
- ## Sprint Goals
8
-
9
- 1. Establish core gem architecture and configuration system
10
- 2. Implement authentication and token lifecycle management
11
- 3. Build HTTP transport layer with Faraday
12
- 4. Create error handling framework
13
- 5. Implement idempotency middleware
14
- 6. Set up testing infrastructure
15
-
16
- ## Sprint Duration
17
-
18
- 2 weeks
19
-
20
- ## Work Items
21
-
22
- ### 1. Core Architecture Setup
23
-
24
- **Priority: Critical**
25
-
26
- #### 1.1 Gem Structure and Module Organization
27
-
28
- - Create directory structure following the architectural blueprint:
29
- ```
30
- lib/airwallex/
31
- ├── api_operations/
32
- ├── resources/
33
- ├── errors.rb
34
- ├── client.rb
35
- ├── configuration.rb
36
- ├── webhook.rb
37
- ├── util.rb
38
- ├── middleware/
39
- │ ├── auth_refresh.rb
40
- │ └── idempotency.rb
41
- └── version.rb
42
- ```
43
-
44
- - Set up `lib/airwallex.rb` as main entry point with configuration block support
45
-
46
- **Acceptance Criteria:**
47
- - Directory structure matches blueprint
48
- - Module can be required without errors
49
- - Configuration block accepts environment, api_key, client_id
50
-
51
- **Estimated Effort:** 2 hours
52
-
53
- #### 1.2 Configuration Management
54
-
55
- - Implement `Airwallex::Configuration` class
56
- - Support environment selection (`:sandbox`, `:production`)
57
- - Dynamic URL generation based on environment
58
- - Default to `:sandbox` for safety
59
- - Validate credential format
60
-
61
- **Key Features:**
62
- ```ruby
63
- Airwallex.configure do |config|
64
- config.api_key = 'key'
65
- config.client_id = 'id'
66
- config.environment = :sandbox
67
- config.api_version = '2024-09-27' # Date-based versioning
68
- end
69
- ```
70
-
71
- **Acceptance Criteria:**
72
- - Configuration persists across requests
73
- - Environment correctly maps to URLs (api-demo vs api)
74
- - Raises error if credentials missing
75
- - Validates environment is :sandbox or :production
76
-
77
- **Estimated Effort:** 4 hours
78
-
79
- ### 2. HTTP Transport Layer
80
-
81
- **Priority: Critical**
82
-
83
- #### 2.1 Faraday Client Setup
84
-
85
- - Configure Faraday connection with TLS 1.2+ enforcement
86
- - Set base URLs for API and Files endpoints
87
- - Configure default headers:
88
- - `Content-Type: application/json`
89
- - `User-Agent: Airwallex-Ruby/{version} Ruby/{ruby_version}`
90
- - `x-api-version` from configuration
91
-
92
- **Acceptance Criteria:**
93
- - Faraday connection established
94
- - Headers correctly injected
95
- - TLS version enforced
96
- - Base URL switches with environment
97
-
98
- **Estimated Effort:** 3 hours
99
-
100
- #### 2.2 Request/Response Middleware Stack
101
-
102
- - JSON request encoding
103
- - JSON response parsing
104
- - Logging middleware (debug mode)
105
- - Configure connection and request timeouts
106
-
107
- **Acceptance Criteria:**
108
- - JSON automatically serialized/deserialized
109
- - Logs show request/response in debug mode
110
- - Timeouts configurable
111
-
112
- **Estimated Effort:** 3 hours
113
-
114
- ### 3. Authentication System
115
-
116
- **Priority: Critical**
117
-
118
- #### 3.1 Bearer Token Authentication
119
-
120
- - Implement `Airwallex::Authentication` module
121
- - POST to `/api/v1/authentication/login`
122
- - Exchange client_id/api_key for Bearer token
123
- - Store token and expiration
124
-
125
- **Key Implementation:**
126
- ```ruby
127
- POST /api/v1/authentication/login
128
- Headers: x-client-id, x-api-key
129
- Response: { token: "...", expires_at: "..." }
130
- ```
131
-
132
- **Acceptance Criteria:**
133
- - Successful token exchange
134
- - Token stored in client instance
135
- - Expiration time tracked
136
- - Handles 401 authentication errors
137
-
138
- **Estimated Effort:** 4 hours
139
-
140
- #### 3.2 Token Lifecycle Management Middleware
141
-
142
- - Implement `Airwallex::Middleware::AuthRefresh`
143
- - Check token expiration before requests (5-minute buffer)
144
- - Auto-refresh expired tokens
145
- - Intercept 401 responses and retry once after refresh
146
- - Thread-safe token management
147
-
148
- **Acceptance Criteria:**
149
- - Token refreshes automatically when expired
150
- - 401 responses trigger refresh and retry
151
- - No double-refresh in concurrent requests
152
- - Transparent to end user
153
-
154
- **Estimated Effort:** 6 hours
155
-
156
- ### 4. Error Handling Framework
157
-
158
- **Priority: Critical**
159
-
160
- #### 4.1 Exception Hierarchy
161
-
162
- Create exception classes mapped to HTTP status codes:
163
-
164
- ```ruby
165
- Airwallex::Error (base)
166
- ├── Airwallex::BadRequestError (400)
167
- ├── Airwallex::AuthenticationError (401)
168
- ├── Airwallex::PermissionError (403)
169
- ├── Airwallex::NotFoundError (404)
170
- ├── Airwallex::RateLimitError (429)
171
- └── Airwallex::APIError (500+)
172
- ```
173
-
174
- **Acceptance Criteria:**
175
- - All error classes defined
176
- - Base error has code, message, param, details attributes
177
- - HTTP status correctly mapped to exception class
178
-
179
- **Estimated Effort:** 3 hours
180
-
181
- #### 4.2 Error Response Parsing
182
-
183
- - Handle polymorphic error body structures
184
- - Parse standard errors: `{ code, message, source }`
185
- - Parse complex errors with details array
186
- - Parse validation errors with nested source paths
187
- - Map `source` to `param` attribute
188
-
189
- **Test Cases:**
190
- - Simple error: `{ code: "insufficient_fund", message: "..." }`
191
- - Complex error: `{ code: "request_id_duplicate", details: [...] }`
192
- - Validation error: `{ code: "invalid_argument", source: "nested.field.path" }`
193
-
194
- **Acceptance Criteria:**
195
- - All error formats parsed correctly
196
- - Detailed error information accessible
197
- - Source field mapped to param
198
-
199
- **Estimated Effort:** 4 hours
200
-
201
- ### 5. Idempotency System
202
-
203
- **Priority: High**
204
-
205
- #### 5.1 Idempotency Middleware
206
-
207
- - Implement `Airwallex::Middleware::Idempotency`
208
- - Auto-generate UUID v4 for `request_id` if not provided
209
- - Inject `request_id` into request body (not headers)
210
- - Preserve user-provided request_id for reconciliation
211
-
212
- **Key Behavior:**
213
- ```ruby
214
- # User doesn't provide request_id
215
- Transfer.create(amount: 100)
216
- # Gem generates: { amount: 100, request_id: "uuid-v4" }
217
-
218
- # User provides request_id
219
- Transfer.create(amount: 100, request_id: "my-id")
220
- # Gem preserves: { amount: 100, request_id: "my-id" }
221
- ```
222
-
223
- **Acceptance Criteria:**
224
- - UUID v4 generated if request_id missing
225
- - User-provided request_id preserved
226
- - request_id injected into body, not headers
227
- - Works for POST/PUT/PATCH methods only
228
-
229
- **Estimated Effort:** 4 hours
230
-
231
- #### 5.2 Retry Logic with Idempotency
232
-
233
- - Implement retry middleware with exponential backoff
234
- - Safe retries for GET requests on 429, 5xx
235
- - Safe retries for POST/PUT/PATCH only if request_id present
236
- - Jittered exponential backoff (prevents thundering herd)
237
- - Max 3 retry attempts
238
-
239
- **Acceptance Criteria:**
240
- - GET requests retried on 429/5xx
241
- - POST with request_id retried safely
242
- - POST without request_id NOT retried
243
- - Backoff includes jitter
244
- - Max retries configurable
245
-
246
- **Estimated Effort:** 5 hours
247
-
248
- ### 6. Testing Infrastructure
249
-
250
- **Priority: High**
251
-
252
- #### 6.1 Test Setup
253
-
254
- - Configure RSpec with spec_helper
255
- - Add WebMock for HTTP stubbing
256
- - Add VCR for recording/replaying HTTP interactions
257
- - Create test fixtures for common responses
258
- - Set up test coverage reporting
259
-
260
- **Acceptance Criteria:**
261
- - RSpec runs successfully
262
- - WebMock blocks real HTTP requests
263
- - VCR configured for sandbox interactions
264
- - Test coverage tracked
265
-
266
- **Estimated Effort:** 3 hours
267
-
268
- #### 6.2 Core Tests
269
-
270
- Write comprehensive tests for:
271
-
272
- - Configuration management
273
- - Authentication flow
274
- - Token refresh logic
275
- - Error parsing (all formats)
276
- - Idempotency key generation
277
- - Retry logic with various scenarios
278
-
279
- **Test Coverage Targets:**
280
- - Configuration: 100%
281
- - Authentication: 100%
282
- - Error handling: 100%
283
- - Middleware: 95%+
284
-
285
- **Acceptance Criteria:**
286
- - All core components tested
287
- - Edge cases covered
288
- - VCR cassettes for sandbox API
289
- - Coverage above 90%
290
-
291
- **Estimated Effort:** 8 hours
292
-
293
- ### 7. Utility Modules
294
-
295
- **Priority: Medium**
296
-
297
- #### 7.1 Date/Time Formatting
298
-
299
- - Implement ISO 8601 serialization helpers
300
- - Accept Ruby Date, Time, DateTime objects
301
- - Convert to "YYYY-MM-DDTHH:MM:SSZ" format
302
- - Handle timezone conversions
303
-
304
- **Acceptance Criteria:**
305
- - Date/Time objects serialized correctly
306
- - ISO 8601 format enforced
307
- - Timezone handling accurate
308
-
309
- **Estimated Effort:** 2 hours
310
-
311
- #### 7.2 BigDecimal Support
312
-
313
- - Configure JSON serialization for BigDecimal
314
- - Add helpers for currency conversion
315
- - Documentation on monetary value handling
316
-
317
- **Acceptance Criteria:**
318
- - BigDecimal serialized without precision loss
319
- - Helper methods available
320
- - Documentation clear
321
-
322
- **Estimated Effort:** 2 hours
323
-
324
- ## Definition of Done
325
-
326
- - [ ] All code follows Rubocop style guide (no offenses)
327
- - [ ] Test coverage above 90%
328
- - [ ] All acceptance criteria met
329
- - [ ] Documentation updated in README
330
- - [ ] Code reviewed by team member
331
- - [ ] Manual testing in sandbox environment
332
- - [ ] No security vulnerabilities (bundle audit clean)
333
-
334
- ## Dependencies and Risks
335
-
336
- ### Dependencies
337
-
338
- - Faraday ~> 2.0
339
- - Faraday-multipart ~> 1.0
340
- - Faraday-retry ~> 2.0
341
- - RSpec ~> 3.12 (dev)
342
- - WebMock ~> 3.18 (dev)
343
- - VCR ~> 6.1 (dev)
344
-
345
- ### Risks
346
-
347
- 1. **Token refresh race conditions**: Mitigated with mutex locks
348
- 2. **Idempotency key collisions**: Use UUID v4 (collision probability negligible)
349
- 3. **API version changes**: Pin to specific tested version (2024-09-27)
350
- 4. **Rate limiting during testing**: Use VCR to replay responses
351
-
352
- ## Success Metrics
353
-
354
- - Core architecture complete and testable
355
- - Authentication works reliably in sandbox
356
- - Idempotency prevents duplicate transactions
357
- - Error handling provides actionable information
358
- - All tests pass consistently
359
- - Zero Rubocop offenses
360
-
361
- ## Out of Scope for Sprint 1
362
-
363
- The following items are deferred to future sprints:
364
-
365
- - Specific resource implementations (Payment, Transfer, etc.)
366
- - Pagination logic (AutoPaginator)
367
- - Webhook signature verification
368
- - OAuth flow support
369
- - SCA token handling
370
- - Platform/Connected Account features (x-on-behalf-of)
371
- - Rate limit headers parsing
372
- - API version override per-request
373
-
374
- ## Sprint Retrospective Topics
375
-
376
- - Was the architectural approach correct?
377
- - Are the abstractions at the right level?
378
- - Is the error handling sufficient?
379
- - How maintainable is the middleware stack?
380
- - What surprised us during implementation?
381
-
382
- ## Next Sprint Preview
383
-
384
- Sprint 2 will focus on:
385
- - Resource base class (APIResource)
386
- - API operations mixins (Create, Retrieve, List)
387
- - Pagination system (cursor and offset)
388
- - First resource implementations (Payment Intent, Transfer)
389
- - Webhook verification