Files
banks2ff/AGENTS.md
Jacob Kiers 3d4ace793d Refine development guidelines for improved code quality
Update the development guide to emphasize best practices including updating specifications during work, mandatory code formatting and linting, README updates for user-visible changes, and cleanup of unused code. This fosters consistent, high-quality contributions that enhance the project's reliability and maintainability.
2025-11-27 21:28:09 +01:00

215 lines
8.5 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
- When working from a spec, update the spec with the current status as soon as you finish something
### 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
- _ALWAYS_ format and lint after making a change, and fix linting errors and warnings
- When a change is end-user visible, update the README.md. Use the README.md documentation guidelines
- Always clean up unused code. No todo's or unused code is allowed after a change
### 4. Commit Standards
- *Always* ensure the workspace compiles: `cargo build --workspace`
- Commit both code and tests together
- Write clear, descriptive commit messages, focusing on user benefits over technical details. Use prose over bullet points
### Version Control
- **Use JJ (Jujutsu)** as the primary tool for all source control operations due to its concurrency and conflict-free design. Use a specialized agent if available
- **Git fallback**: Only for complex operations unsupported by JJ (e.g., interactive rebasing)
## 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 sparingly for implementation details. *Do* explain complex logic