Files
banks2ff/AGENTS.md

241 lines
9.8 KiB
Markdown
Raw Permalink Normal View History

2025-11-19 21:18:37 +00:00
# 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**
2025-11-19 21:18:37 +00:00
**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
2025-11-19 21:18:37 +00:00
**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
2025-11-19 21:18:37 +00:00
### **Compliance Protocol for AI Agent Debugging**
When debugging financial data issues with AI agents:
2025-11-19 21:18:37 +00:00
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
2025-11-19 21:18:37 +00:00
```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
- **MANDATORY**: After making ANY code change, complete the Post-Change Verification Checklist (see Code Quality section below)
2025-11-19 21:18:37 +00:00
### 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
- **MANDATORY: ALWAYS format and lint after making ANY change, and fix ALL 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. Remove unused variables, functions, imports, etc. Do NOT hide unused code with underscores - delete it!
#### Post-Change Verification Checklist (MANDATORY)
After making ANY code change, you MUST run these commands and fix any issues:
1. **Format code**: `cargo fmt --all`
2. **Run linter**: `cargo clippy --all-targets --all-features -- -D warnings`
3. **Run tests**: `cargo test --workspace`
4. **Build project**: `cargo build --workspace`
5. **Clean up unused code**: Remove any unused variables, functions, imports, etc.
**FAILURE TO COMPLETE THIS CHECKLIST WILL RESULT IN CODE REJECTION**
2025-11-19 21:18:37 +00:00
### 4. Commit Standards
- *Always* ensure the workspace compiles: `cargo build --workspace`
2025-11-19 21:18:37 +00:00
- Commit both code and tests together
- Write clear, descriptive commit messages, focusing on user benefits over technical details. Use prose over bullet points
2025-11-19 21:18:37 +00:00
### 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)
2025-11-19 21:18:37 +00:00
## 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
### Commands Module (`banks2ff/src/commands/`)
- **sync.rs**: Sync command handler
- **accounts/**: Account management commands
- **mod.rs**: Account command dispatch
- **link.rs**: Account linking logic and LinkCommands dispatch
- **list.rs**: Account listing handler
- **status.rs**: Account status handler
- **transactions/**: Transaction management commands
- **mod.rs**: Transaction command dispatch
- **list.rs**: Transaction listing handler
- **cache.rs**: Cache status handler
- **clear.rs**: Cache clearing handler
- **list.rs**: Source/destination listing handler
2025-11-19 21:18:37 +00:00
### 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