- Implement robust End User Agreement expiry detection and handling - Add graceful error recovery for failed accounts - Rewrite README.md to focus on user benefits - Add documentation guidelines to AGENTS.md
206 lines
7.8 KiB
Markdown
206 lines
7.8 KiB
Markdown
# Banks2FF Development Guide
|
|
|
|
## Project Purpose
|
|
|
|
Banks2FF is a Rust CLI tool that synchronizes bank transactions from GoCardless Bank Account Data API to Firefly III personal finance manager. It implements a hexagonal architecture for clean separation of concerns and comprehensive testing.
|
|
|
|
## 🚨 CRITICAL: Financial Data Security
|
|
|
|
### **Financial Data Masking Requirements**
|
|
|
|
**FOR LLM/AI INTERACTIONS ONLY**: When interacting with coding agents, LLMs, or AI assistants:
|
|
- **NEVER** expose, log, or display raw financial information including:
|
|
- Transaction amounts
|
|
- Account balances
|
|
- IBANs or account numbers
|
|
- Transaction descriptions
|
|
- Personal identifiers
|
|
- API keys or tokens
|
|
|
|
**FOR DEBUG LOGGING**: When using `RUST_LOG=debug`:
|
|
- **STRUCTURED LOGGING** shows HTTP requests, responses, and errors
|
|
- **NO SENSITIVE DATA** is logged (financial amounts, personal info, tokens)
|
|
- **REQUEST TRACING** includes method, URL, status codes, and error details
|
|
|
|
### **Compliance Protocol for AI Agent Debugging**
|
|
|
|
When debugging financial data issues with AI agents:
|
|
|
|
1. **Create Anonymized Test Scripts**: Write small, focused scripts that extract only the necessary data structure information
|
|
2. **Use Mock Data**: Replace real financial values with placeholder data
|
|
3. **Validate Structure, Not Values**: Focus on data structure integrity, not actual financial content
|
|
4. **Sanitize All Outputs**: Ensure any debugging output masks sensitive information
|
|
|
|
### **Debug Logging**
|
|
|
|
The application uses structured logging with the `tracing` crate:
|
|
|
|
- **Normal operation**: Uses INFO level logging for key operations
|
|
- **Debug mode**: Set `RUST_LOG=debug` to see detailed HTTP request/response logging
|
|
- **No sensitive data**: Financial amounts and personal information are never logged
|
|
- **Request tracing**: HTTP method, URL, status codes, and error responses are logged
|
|
|
|
```rust
|
|
// ✅ GOOD: Structure validation with mock data
|
|
fn validate_transaction_structure() {
|
|
let mock_tx = BankTransaction {
|
|
amount: Decimal::new(12345, 2), // Mock amount
|
|
currency: "EUR".to_string(),
|
|
// ... other fields with mock data
|
|
};
|
|
// Validate structure only
|
|
}
|
|
|
|
// ❌ BAD: Exposing real financial data
|
|
fn debug_real_transactions(transactions: Vec<BankTransaction>) {
|
|
for tx in transactions {
|
|
println!("Real amount: {}", tx.amount); // SECURITY VIOLATION
|
|
}
|
|
}
|
|
```
|
|
|
|
## Rust Development Best Practices
|
|
|
|
### Error Handling
|
|
|
|
- **Use `thiserror`** for domain-specific error types in core modules
|
|
- **Use `anyhow`** for application-level error context and propagation
|
|
- **Never use `panic!`** in production code - handle errors gracefully
|
|
- **Implement `From` traits** for error type conversions
|
|
|
|
```rust
|
|
// Core domain errors
|
|
#[derive(Error, Debug)]
|
|
pub enum SyncError {
|
|
#[error("Failed to fetch transactions from source: {0}")]
|
|
SourceError(#[from] anyhow::Error),
|
|
#[error("Failed to store transaction: {0}")]
|
|
DestinationError(#[from] anyhow::Error),
|
|
}
|
|
```
|
|
|
|
### Async Programming
|
|
|
|
- **Use `tokio`** as the async runtime (workspace dependency)
|
|
- **Prefer `async-trait`** for trait methods that need to be async
|
|
- **Handle cancellation** properly with `select!` or `tokio::time::timeout`
|
|
- **Use `?` operator** for error propagation in async functions
|
|
|
|
### Testing Strategy
|
|
|
|
- **Unit Tests**: Test pure functions and business logic in isolation
|
|
- **Integration Tests**: Test adapter implementations with `wiremock`
|
|
- **Mock External Dependencies**: Use `mockall` for trait-based testing
|
|
- **Test Fixtures**: Store sample JSON responses in `tests/fixtures/`
|
|
|
|
```rust
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use mockall::predicate::*;
|
|
|
|
#[tokio::test]
|
|
async fn test_sync_with_mock_source() {
|
|
let mut mock_source = MockTransactionSource::new();
|
|
// Setup mock expectations
|
|
// Test core logic
|
|
}
|
|
}
|
|
```
|
|
|
|
### Code Organization
|
|
|
|
- **Workspace Dependencies**: Define common dependencies in root `Cargo.toml`
|
|
- **Feature Flags**: Use features for optional functionality
|
|
- **Module Structure**: Keep modules focused and single-responsibility
|
|
- **Public API**: Minimize public surface area; prefer internal modules
|
|
|
|
### Dependencies and Patterns
|
|
|
|
**Key Workspace Dependencies:**
|
|
- `tokio`: Async runtime with full features
|
|
- `reqwest`: HTTP client with JSON support
|
|
- `serde`/`serde_json`: Serialization/deserialization
|
|
- `chrono`: Date/time handling with serde support
|
|
- `rust_decimal`: Precise decimal arithmetic for financial data
|
|
- `tracing`/`tracing-subscriber`: Structured logging
|
|
- `clap`: CLI argument parsing with derive macros
|
|
- `anyhow`/`thiserror`: Error handling
|
|
- `async-trait`: Async trait support
|
|
- `wiremock`: HTTP mocking for tests
|
|
- `mockall`: Runtime mocking for tests
|
|
|
|
## Development Workflow
|
|
|
|
### 1. Code Development
|
|
- Write code in appropriate modules following the hexagonal architecture
|
|
- Keep core business logic separate from external integrations
|
|
- Use workspace dependencies consistently
|
|
|
|
### 2. Testing
|
|
- Write tests alongside code in `#[cfg(test)]` modules
|
|
- Test both happy path and error conditions
|
|
- Use mock objects for external dependencies
|
|
- Ensure all tests pass: `cargo test --workspace`
|
|
|
|
### 3. Code Quality
|
|
- Follow Rust idioms and conventions
|
|
- Use `cargo fmt` for formatting
|
|
- Use `cargo clippy` for linting
|
|
- Ensure documentation for public APIs
|
|
|
|
### 4. Commit Standards
|
|
- Commit both code and tests together
|
|
- Write clear, descriptive commit messages
|
|
- Ensure the workspace compiles: `cargo build --workspace`
|
|
|
|
## Project Structure Guidelines
|
|
|
|
### Core Module (`banks2ff/src/core/`)
|
|
- **models.rs**: Domain entities (BankTransaction, Account)
|
|
- **ports.rs**: Trait definitions (TransactionSource, TransactionDestination)
|
|
- **sync.rs**: Business logic orchestration
|
|
|
|
### Adapters Module (`banks2ff/src/adapters/`)
|
|
- **gocardless/**: GoCardless API integration
|
|
- **firefly/**: Firefly III API integration
|
|
- Each adapter implements the appropriate port trait
|
|
|
|
### Client Libraries
|
|
- **gocardless-client/**: Standalone GoCardless API wrapper
|
|
- **firefly-client/**: Standalone Firefly III API wrapper
|
|
- Both use `reqwest` for HTTP communication
|
|
|
|
## Security Considerations
|
|
|
|
- **Never log sensitive data**: Use tracing filters to exclude financial information
|
|
- **Environment variables**: Store credentials in `.env` file (never in code)
|
|
- **Input validation**: Validate all external data before processing
|
|
- **Error messages**: Don't expose sensitive information in error messages
|
|
|
|
## Performance Considerations
|
|
|
|
- **Caching**: Use caching to reduce API calls (see GoCardlessAdapter)
|
|
- **Rate Limiting**: Handle 429 responses gracefully
|
|
- **Batch Processing**: Process transactions in reasonable batches
|
|
- **Async Concurrency**: Use `tokio` for concurrent operations where appropriate
|
|
|
|
## Observability
|
|
|
|
- **Structured Logging**: Use `tracing` with spans for operations
|
|
- **Error Context**: Provide context in error messages for debugging
|
|
- **Metrics**: Consider adding metrics for sync operations
|
|
- **Log Levels**: Use appropriate log levels (debug, info, warn, error)
|
|
|
|
## Documentation Guidelines
|
|
|
|
### README.md
|
|
- **Keep High-Level**: Focus on user benefits and key features, not technical implementation details
|
|
- **User-Centric**: Describe what the tool does and why users would want it
|
|
- **Skip Implementation Details**: Avoid technical jargon, architecture specifics, or internal implementation that users don't need to know
|
|
- **Feature Descriptions**: Use concise, benefit-focused language (e.g., "Robust Error Handling" rather than "Implements EUA expiry detection with multiple requisition fallback")
|
|
|
|
### Technical Documentation
|
|
- **docs/architecture.md**: Detailed technical specifications, implementation details, and developer-focused content
|
|
- **specs/**: Implementation planning, API specifications, and historical context
|
|
- **Code Comments**: Use for implementation details and complex logic explanations |