docs: map existing codebase
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
# Architecture
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-02-28
|
||||||
|
|
||||||
|
## Pattern Overview
|
||||||
|
|
||||||
|
**Overall:** Single-Binary CLI/TUI Application (Rust)
|
||||||
|
|
||||||
|
**Key Characteristics:**
|
||||||
|
- Monolithic Rust binary using Ratatui for terminal UI
|
||||||
|
- Minimal dependency footprint (only Ratatui as external dependency)
|
||||||
|
- Single entry point with main function
|
||||||
|
- Early-stage project with foundational structure only
|
||||||
|
|
||||||
|
## Layers
|
||||||
|
|
||||||
|
**Presentation Layer:**
|
||||||
|
- Purpose: Terminal user interface rendering and interaction
|
||||||
|
- Location: `src/main.rs` (currently)
|
||||||
|
- Contains: TUI initialization, event handling, widget rendering
|
||||||
|
- Depends on: Ratatui framework
|
||||||
|
- Used by: End users through terminal
|
||||||
|
|
||||||
|
**Business Logic Layer:**
|
||||||
|
- Purpose: Core application functionality
|
||||||
|
- Location: TBD - not yet implemented
|
||||||
|
- Contains: Data processing, command handling, state management
|
||||||
|
- Depends on: None currently defined
|
||||||
|
- Used by: Presentation layer
|
||||||
|
|
||||||
|
**Data Layer:**
|
||||||
|
- Purpose: Data persistence and retrieval
|
||||||
|
- Location: TBD - not yet implemented
|
||||||
|
- Contains: File I/O, caching, serialization
|
||||||
|
- Depends on: Standard library (File, IO)
|
||||||
|
- Used by: Business logic layer
|
||||||
|
|
||||||
|
## Data Flow
|
||||||
|
|
||||||
|
**Typical User Interaction Flow:**
|
||||||
|
|
||||||
|
1. Terminal input captured by Ratatui event handling
|
||||||
|
2. User action (keyboard/mouse) parsed into application command
|
||||||
|
3. Command dispatched to business logic handler
|
||||||
|
4. Handler processes request, potentially reads/writes data
|
||||||
|
5. State updated based on result
|
||||||
|
6. UI re-rendered with new state in next frame
|
||||||
|
|
||||||
|
**State Management:**
|
||||||
|
- Single application state entity (not yet defined)
|
||||||
|
- Immutable state passed to rendering function
|
||||||
|
- Ratatui handles incremental screen updates
|
||||||
|
|
||||||
|
## Key Abstractions
|
||||||
|
|
||||||
|
**Terminal User Interface (TUI):**
|
||||||
|
- Purpose: Encapsulate all terminal rendering and input handling
|
||||||
|
- Examples: `src/main.rs` (current single module)
|
||||||
|
- Pattern: React-like paradigm via Ratatui (state -> render)
|
||||||
|
|
||||||
|
**Application Command/Action:**
|
||||||
|
- Purpose: Abstract user intentions from input events
|
||||||
|
- Examples: Not yet implemented
|
||||||
|
- Pattern: Enum-based command pattern expected
|
||||||
|
|
||||||
|
## Entry Points
|
||||||
|
|
||||||
|
**Binary Entry:**
|
||||||
|
- Location: `src/main.rs`
|
||||||
|
- Triggers: `cargo run` or binary execution
|
||||||
|
- Responsibilities:
|
||||||
|
- Initialize Ratatui terminal
|
||||||
|
- Set up event loop
|
||||||
|
- Handle application lifecycle
|
||||||
|
- Render UI each frame
|
||||||
|
- Currently: Placeholder with "Hello, world!" output
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
**Strategy:** Not yet defined
|
||||||
|
|
||||||
|
**Patterns:**
|
||||||
|
- Ratatui provides Result types for I/O operations
|
||||||
|
- Expected approach: Result-based error propagation using ? operator
|
||||||
|
- Terminal restoration should be ensured on panic (Ratatui provides Drop impl)
|
||||||
|
|
||||||
|
## Cross-Cutting Concerns
|
||||||
|
|
||||||
|
**Logging:** Not yet implemented. Standard approach would use `log` crate or println! macros during development.
|
||||||
|
|
||||||
|
**Validation:** Not yet implemented. Expected in business logic layer once commands are defined.
|
||||||
|
|
||||||
|
**Terminal State:** Ratatui manages terminal state (raw mode, cursor visibility, etc.). Must ensure proper cleanup on application exit.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Architecture analysis: 2026-02-28*
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
# Codebase Concerns
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-02-28
|
||||||
|
|
||||||
|
## Critical Issues
|
||||||
|
|
||||||
|
**Empty Application Stub:**
|
||||||
|
- Issue: The entire application is a bare "Hello, world!" stub with no functional implementation
|
||||||
|
- Files: `src/main.rs`
|
||||||
|
- Impact: No actual BBS markdown functionality exists; application is not usable
|
||||||
|
- Fix approach: Implement core application logic for markdown bulletin board system functionality
|
||||||
|
|
||||||
|
**Invalid Edition Specification:**
|
||||||
|
- Issue: `Cargo.toml` specifies `edition = "2024"` which is not a valid Rust edition
|
||||||
|
- Files: `Cargo.toml`
|
||||||
|
- Impact: Build will fail or behave unexpectedly if edition validation is enforced; incorrect edition can affect language feature availability
|
||||||
|
- Fix approach: Change to a valid edition: `2021` (latest stable) or `2018` if legacy support needed
|
||||||
|
|
||||||
|
## Tech Debt
|
||||||
|
|
||||||
|
**Minimal Dependency Management:**
|
||||||
|
- Issue: Heavy dependency on ratatui (0.30.0) and its entire ecosystem for a stub application
|
||||||
|
- Files: `Cargo.toml`
|
||||||
|
- Impact: Unnecessary compiled binary size and build time for functionality that doesn't yet exist; approximately 60+ transitive dependencies for "Hello, world!"
|
||||||
|
- Fix approach: Keep ratatui when actual TUI is implemented; document why ratatui was chosen early
|
||||||
|
|
||||||
|
**No Error Handling:**
|
||||||
|
- Issue: Application has no error handling, logging, or graceful failure modes
|
||||||
|
- Files: `src/main.rs`
|
||||||
|
- Impact: Crashes will be silent or unhelpful; no debugging information available
|
||||||
|
- Fix approach: Implement structured error handling; consider using `anyhow` or `thiserror` crate (already available in dependencies)
|
||||||
|
|
||||||
|
**No Architecture Documentation:**
|
||||||
|
- Issue: Zero guidance on how BBS-MD should be structured or what features should be implemented
|
||||||
|
- Files: Project root (missing design docs)
|
||||||
|
- Impact: Development direction unclear; future contributors won't understand intent
|
||||||
|
- Fix approach: Create architecture documentation, feature specification, and roadmap
|
||||||
|
|
||||||
|
## Missing Critical Features
|
||||||
|
|
||||||
|
**No TUI Implementation:**
|
||||||
|
- What's missing: Terminal UI is imported (ratatui) but never used
|
||||||
|
- Blocks: Cannot create/view/edit bulletin board content
|
||||||
|
- Priority: High
|
||||||
|
|
||||||
|
**No Data Persistence:**
|
||||||
|
- What's missing: No markdown file handling, no storage mechanism
|
||||||
|
- Blocks: Cannot persist BBS posts or configuration
|
||||||
|
- Priority: High
|
||||||
|
|
||||||
|
**No Input Processing:**
|
||||||
|
- What's missing: Application ignores user input entirely
|
||||||
|
- Blocks: Cannot interact with application
|
||||||
|
- Priority: High
|
||||||
|
|
||||||
|
## Test Coverage Gaps
|
||||||
|
|
||||||
|
**Zero Testing:**
|
||||||
|
- What's not tested: All functionality (or complete lack thereof)
|
||||||
|
- Files: No test directory exists; `src/main.rs` has no tests
|
||||||
|
- Risk: No confidence in correctness; refactoring will be dangerous
|
||||||
|
- Priority: High
|
||||||
|
|
||||||
|
## Scalability & Architecture Concerns
|
||||||
|
|
||||||
|
**Monolithic Structure:**
|
||||||
|
- Problem: Single main.rs file will quickly become unmaintainable as features are added
|
||||||
|
- Current capacity: ~45 lines before severe maintainability issues
|
||||||
|
- Scaling path: Create modular structure with separate modules for TUI layer, data layer, business logic
|
||||||
|
|
||||||
|
**Dependency Organization:**
|
||||||
|
- Problem: Entire ratatui ecosystem locked in at build time even when not used
|
||||||
|
- Current capacity: 60+ transitive dependencies inflating binary
|
||||||
|
- Scaling path: Feature-gate dependencies or defer dependency addition until features are implemented
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
**Unvalidated Input:**
|
||||||
|
- Risk: Once input processing is added, no visible validation or sanitization strategy exists
|
||||||
|
- Files: Will be implemented in future features
|
||||||
|
- Current mitigation: None (application ignores input)
|
||||||
|
- Recommendations: Plan input validation for markdown parsing; sanitize user-provided content if displayed; consider file path traversal protections if file loading is implemented
|
||||||
|
|
||||||
|
**File System Access:**
|
||||||
|
- Risk: Future markdown file handling could expose security issues (directory traversal, privilege escalation)
|
||||||
|
- Files: Not yet implemented
|
||||||
|
- Current mitigation: None
|
||||||
|
- Recommendations: When implementing file I/O, enforce strict path validation; restrict operations to designated directories only
|
||||||
|
|
||||||
|
## Dependencies at Risk
|
||||||
|
|
||||||
|
**Edition Mismatch:**
|
||||||
|
- Risk: Invalid edition specification may cause build failures or unexpected behavior in future toolchain versions
|
||||||
|
- Impact: Application may not compile with newer Rust tools
|
||||||
|
- Migration plan: Immediately fix to `edition = "2021"` to match stable toolchain
|
||||||
|
|
||||||
|
**Tight Coupling to Ratatui:**
|
||||||
|
- Risk: Early adoption of specific TUI framework before requirements are clear
|
||||||
|
- Impact: Switching frameworks later will require significant refactoring
|
||||||
|
- Migration plan: Encapsulate ratatui behind abstraction layer; consider generic TUI trait to allow future framework swaps
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Concerns audit: 2026-02-28*
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
# Coding Conventions
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-02-28
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This is an early-stage Rust project with minimal codebase (single `main.rs` file). Conventions are established based on:
|
||||||
|
- Rust language defaults and community standards
|
||||||
|
- Cargo default behavior
|
||||||
|
- Current code patterns in the project
|
||||||
|
|
||||||
|
## Naming Patterns
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Snake case: `main.rs`, `lib.rs` are standard entry points
|
||||||
|
- Module files use snake_case: `user_service.rs`, `data_handler.rs`
|
||||||
|
- Test modules within files or in separate `tests/` directory
|
||||||
|
|
||||||
|
**Functions:**
|
||||||
|
- Snake case throughout: `fn handle_connection()`, `fn parse_input()`
|
||||||
|
- Use descriptive verb-based names: `fn calculate_sum()`, `fn build_response()`
|
||||||
|
|
||||||
|
**Variables:**
|
||||||
|
- Snake case for bindings: `let user_id`, `let response_data`
|
||||||
|
- Constants use UPPER_CASE: `const MAX_BUFFER_SIZE: usize = 1024`
|
||||||
|
- Mutable bindings explicitly marked: `let mut count = 0`
|
||||||
|
|
||||||
|
**Types and Structs:**
|
||||||
|
- PascalCase for type names: `struct User`, `enum Status`, `trait Handler`
|
||||||
|
- Generic parameters use single letters or PascalCase: `T`, `S`, `Request`
|
||||||
|
- Lifetime parameters use lowercase: `'a`, `'static`
|
||||||
|
|
||||||
|
## Code Style
|
||||||
|
|
||||||
|
**Formatting:**
|
||||||
|
- Default Rust formatting applied by `rustfmt` (de facto standard)
|
||||||
|
- 4-space indentation (Rust default)
|
||||||
|
- No semicolons in final expressions that return values
|
||||||
|
- Closing braces on same line except for block statements
|
||||||
|
|
||||||
|
**Linting:**
|
||||||
|
- Clippy lints should be addressed as part of development
|
||||||
|
- No explicit `clippy.toml` or linting configuration currently present
|
||||||
|
- Default clippy warnings and errors should be resolved before commit
|
||||||
|
|
||||||
|
**Edition:**
|
||||||
|
- Rust 2024 edition (specified in `Cargo.toml`)
|
||||||
|
- Supports latest language features and idioms
|
||||||
|
|
||||||
|
## Import Organization
|
||||||
|
|
||||||
|
**Order:**
|
||||||
|
1. Standard library imports (`use std::`)
|
||||||
|
2. External crate imports (`use ratatui::`, other external deps)
|
||||||
|
3. Internal crate imports (`use crate::`)
|
||||||
|
4. Module declarations (`mod xyz;`)
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```rust
|
||||||
|
use std::io;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use ratatui::backend::CrosstermBackend;
|
||||||
|
use ratatui::Terminal;
|
||||||
|
|
||||||
|
use crate::ui::draw;
|
||||||
|
use crate::handler::InputHandler;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Path Aliases:**
|
||||||
|
- No path aliases configured currently
|
||||||
|
- Can be added via workspace root configuration if needed
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
**Patterns:**
|
||||||
|
- Use `Result<T, E>` for fallible operations
|
||||||
|
- Propagate errors with `?` operator rather than unwrapping when possible
|
||||||
|
- Use `anyhow::Result` for application-level errors (dependency available)
|
||||||
|
- Only use `.unwrap()` or `.expect()` for code that should never panic in normal operation
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```rust
|
||||||
|
fn read_config(path: &str) -> Result<Config> {
|
||||||
|
let content = std::fs::read_to_string(path)?;
|
||||||
|
let config = serde_json::from_str(&content)?;
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
**Framework:** Not yet selected/integrated
|
||||||
|
|
||||||
|
**When logging is added:**
|
||||||
|
- Use `log` crate for production logging
|
||||||
|
- Use `env_logger` or similar for log configuration
|
||||||
|
- Log levels: ERROR for failures, WARN for unusual conditions, INFO for significant events, DEBUG for detailed traces
|
||||||
|
- Avoid logging sensitive data (credentials, tokens, PII)
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
**When to Comment:**
|
||||||
|
- Explain the "why" not the "what"
|
||||||
|
- Document non-obvious algorithmic decisions
|
||||||
|
- Explain trade-offs or workarounds
|
||||||
|
- Mark intentional violations of conventions with `// FIXME:` or `// TODO:`
|
||||||
|
|
||||||
|
**Doc Comments:**
|
||||||
|
- Use `///` for public item documentation
|
||||||
|
- Document public functions, structs, enums, traits
|
||||||
|
- Include examples for complex or non-obvious public APIs
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```rust
|
||||||
|
/// Processes a user command from the input buffer.
|
||||||
|
///
|
||||||
|
/// This function parses the raw input and dispatches to appropriate handlers.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// * `input` - Raw user input string
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// `Result<CommandResult, Error>` indicating success or the error encountered
|
||||||
|
pub fn process_command(input: &str) -> Result<CommandResult> {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Function Design
|
||||||
|
|
||||||
|
**Size:**
|
||||||
|
- Keep functions small and focused (ideally < 50 lines)
|
||||||
|
- Extract helper functions for complex logic
|
||||||
|
- Separate parsing, validation, and execution logic
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- Use owned values for simple types, references for larger types
|
||||||
|
- Prefer `&[T]` over `&Vec<T>` for function parameters
|
||||||
|
- Use structs to group related parameters (> 3 related params)
|
||||||
|
|
||||||
|
**Return Values:**
|
||||||
|
- Use `Result<T, E>` for operations that can fail
|
||||||
|
- Use `Option<T>` for values that may be absent
|
||||||
|
- Avoid returning `Box<dyn Trait>` unless necessary for dynamic dispatch
|
||||||
|
|
||||||
|
## Module Design
|
||||||
|
|
||||||
|
**Exports:**
|
||||||
|
- Explicitly declare public items with `pub`
|
||||||
|
- Use `pub use` to re-export important types at module boundaries
|
||||||
|
- Keep implementation details private (`non-pub` by default)
|
||||||
|
|
||||||
|
**Module Structure:**
|
||||||
|
```rust
|
||||||
|
// src/main.rs
|
||||||
|
mod ui;
|
||||||
|
mod handler;
|
||||||
|
mod model;
|
||||||
|
|
||||||
|
use ui::App;
|
||||||
|
use handler::InputHandler;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Implementation
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Barrel Files:**
|
||||||
|
- Use `mod.rs` files in subdirectories to organize module exports
|
||||||
|
- Example: `src/ui/mod.rs` exports types from `ui/draw.rs`, `ui/state.rs`
|
||||||
|
|
||||||
|
## Unsafe Code
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
- Avoid unsafe blocks unless necessary for FFI or performance-critical code
|
||||||
|
- Document unsafe code with `// SAFETY:` comments explaining invariants
|
||||||
|
- Minimize unsafe scope
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```rust
|
||||||
|
// SAFETY: ptr is guaranteed to point to valid, initialized memory
|
||||||
|
// returned from foreign_function, which owns its lifetime
|
||||||
|
unsafe {
|
||||||
|
let result = process_data(ptr);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Workspace and Multi-Crate Structure
|
||||||
|
|
||||||
|
**Currently:** Single binary crate (`bbs-md`)
|
||||||
|
|
||||||
|
**If expanding:**
|
||||||
|
- Consider separating into `bbs-md` (binary) and `bbs-md-core` (library)
|
||||||
|
- Use workspace for shared dependencies and configuration
|
||||||
|
- Place library code in `src/lib.rs`, binary-specific code in `src/main.rs`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Convention analysis: 2026-02-28*
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
# External Integrations
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-02-28
|
||||||
|
|
||||||
|
## APIs & External Services
|
||||||
|
|
||||||
|
**Not detected** - This is a standalone TUI application with no external API integrations.
|
||||||
|
|
||||||
|
## Data Storage
|
||||||
|
|
||||||
|
**Databases:**
|
||||||
|
- Not detected - No database client/ORM dependencies present
|
||||||
|
|
||||||
|
**File Storage:**
|
||||||
|
- Local filesystem only - Markdown files read/written to local disk
|
||||||
|
|
||||||
|
**Caching:**
|
||||||
|
- Not detected - No external caching service
|
||||||
|
|
||||||
|
## Authentication & Identity
|
||||||
|
|
||||||
|
**Auth Provider:**
|
||||||
|
- Custom or None - No authentication framework detected
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
- Local-only TUI application with no user authentication layer
|
||||||
|
|
||||||
|
## Monitoring & Observability
|
||||||
|
|
||||||
|
**Error Tracking:**
|
||||||
|
- Not detected - No error tracking service integration
|
||||||
|
|
||||||
|
**Logs:**
|
||||||
|
- Standard output/stderr via log crate facade
|
||||||
|
- Controlled via application logging configuration
|
||||||
|
|
||||||
|
## CI/CD & Deployment
|
||||||
|
|
||||||
|
**Hosting:**
|
||||||
|
- Standalone binary deployment - Compiled as single executable
|
||||||
|
|
||||||
|
**CI Pipeline:**
|
||||||
|
- Not detected - No CI/CD configuration files present
|
||||||
|
|
||||||
|
## Environment Configuration
|
||||||
|
|
||||||
|
**Required env vars:**
|
||||||
|
- None detected - Configuration appears to be hardcoded or via CLI arguments
|
||||||
|
|
||||||
|
**Secrets location:**
|
||||||
|
- Not applicable - No external service credentials required
|
||||||
|
|
||||||
|
## Webhooks & Callbacks
|
||||||
|
|
||||||
|
**Incoming:**
|
||||||
|
- Not applicable - Standalone CLI application
|
||||||
|
|
||||||
|
**Outgoing:**
|
||||||
|
- Not applicable - No webhook support detected
|
||||||
|
|
||||||
|
## Terminal Environment
|
||||||
|
|
||||||
|
**Integration Points:**
|
||||||
|
- Terminal protocol: VT100 escape sequences
|
||||||
|
- Platform support via crossterm:
|
||||||
|
- Unix/Linux systems: Raw mode via termios
|
||||||
|
- Windows systems: Windows API for console mode
|
||||||
|
- macOS: POSIX terminal support
|
||||||
|
|
||||||
|
**Signal Handling:**
|
||||||
|
- Unix signals (SIGTERM, SIGINT) for graceful shutdown
|
||||||
|
- Integrated via signal-hook and mio event loop
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Integration audit: 2026-02-28*
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
# Technology Stack
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-02-28
|
||||||
|
|
||||||
|
## Languages
|
||||||
|
|
||||||
|
**Primary:**
|
||||||
|
- Rust - CLI/TUI application for markdown bulletin board system
|
||||||
|
|
||||||
|
## Runtime
|
||||||
|
|
||||||
|
**Environment:**
|
||||||
|
- Rust compiler and runtime
|
||||||
|
|
||||||
|
**Package Manager:**
|
||||||
|
- Cargo
|
||||||
|
- Lockfile: `Cargo.lock` present
|
||||||
|
|
||||||
|
## Frameworks
|
||||||
|
|
||||||
|
**Core:**
|
||||||
|
- ratatui 0.30.0 - Terminal user interface (TUI) framework for building rich CLI applications
|
||||||
|
|
||||||
|
**Build:**
|
||||||
|
- cargo - Rust package manager and build system
|
||||||
|
|
||||||
|
## Key Dependencies
|
||||||
|
|
||||||
|
**Critical:**
|
||||||
|
- ratatui 0.30.0 - Main TUI framework providing terminal rendering, event handling, and widgets
|
||||||
|
- ratatui-core - Core functionality for ratatui
|
||||||
|
- ratatui-crossterm - Crossterm backend integration for ratatui
|
||||||
|
- ratatui-macros - Proc macros for ratatui
|
||||||
|
- ratatui-termwiz - Termwiz backend support for ratatui
|
||||||
|
- ratatui-widgets - Widget library for ratatui
|
||||||
|
|
||||||
|
**Terminal & Input:**
|
||||||
|
- crossterm 0.29.0 - Cross-platform terminal manipulation library (Windows/Unix compatible)
|
||||||
|
- signal-hook - Unix signal handling for clean shutdowns
|
||||||
|
- signal-hook-mio - Integration between signal-hook and mio
|
||||||
|
- termwiz - Terminal operations library with wide character support
|
||||||
|
- terminfo - Terminal capability detection
|
||||||
|
- vtparse - VT100 escape sequence parser
|
||||||
|
- utf8parse - UTF-8 parsing utilities
|
||||||
|
|
||||||
|
**UI Rendering & Text:**
|
||||||
|
- unicode-width - Calculate display width of unicode characters
|
||||||
|
- unicode-truncate - Truncate unicode strings to display width
|
||||||
|
- unicode-segmentation - Segment unicode text
|
||||||
|
- wezterm-bidi - Bidirectional text support
|
||||||
|
- fancy-regex - Advanced regex support with lookahead/lookbehind
|
||||||
|
- regex 1.x - Regular expression library
|
||||||
|
|
||||||
|
**Graphics & Color:**
|
||||||
|
- csscolorparser 0.6.2 - Parse CSS color strings
|
||||||
|
- wezterm-color-types - Color type definitions
|
||||||
|
- euclid - 2D and 3D geometry primitives
|
||||||
|
- line-clipping - Line clipping algorithms
|
||||||
|
|
||||||
|
**Data Structures & Utilities:**
|
||||||
|
- indexmap - Hash map preserving insertion order
|
||||||
|
- hashbrown - Faster hashmap implementation
|
||||||
|
- smallvec - Vector that stores small amounts inline
|
||||||
|
- itertools - Iterator extensions
|
||||||
|
- nom - Parser combinators library
|
||||||
|
- pest - PEG parser generator
|
||||||
|
- strum/strum_macros - Enum utilities and macros
|
||||||
|
|
||||||
|
**Serialization:**
|
||||||
|
- serde/serde_json - Serialization framework
|
||||||
|
- base64 - Base64 encoding/decoding
|
||||||
|
|
||||||
|
**Error Handling:**
|
||||||
|
- anyhow 1.0.102 - Flexible error handling
|
||||||
|
- thiserror - Structured error types
|
||||||
|
|
||||||
|
**Platform Support:**
|
||||||
|
- libc - C library bindings (Unix)
|
||||||
|
- rustix - Wrapper around system calls
|
||||||
|
- nix - Unix-like API bindings
|
||||||
|
- winapi - Windows API bindings
|
||||||
|
- windows-sys - Windows system APIs
|
||||||
|
- parking_lot - Synchronization primitives
|
||||||
|
|
||||||
|
**Hashing & Crypto:**
|
||||||
|
- sha2 - SHA-2 digest algorithms
|
||||||
|
- xxhash-rust - xxHash algorithm
|
||||||
|
|
||||||
|
**UUID & ID Generation:**
|
||||||
|
- uuid - UUID generation and parsing
|
||||||
|
- mac_address - MAC address utilities
|
||||||
|
|
||||||
|
**Logging:**
|
||||||
|
- log - Logging facade
|
||||||
|
|
||||||
|
**Development & Macros:**
|
||||||
|
- syn - Rust syntax tree parsing
|
||||||
|
- quote - Quoting for proc macros
|
||||||
|
- proc-macro2 - Proc macro utilities
|
||||||
|
- darling - Attribute macro argument parsing
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
**Build Configuration:**
|
||||||
|
- Edition: 2024 (Rust edition)
|
||||||
|
- Target: Binary executable
|
||||||
|
- Manifest: `Cargo.toml`
|
||||||
|
|
||||||
|
**Dependencies Management:**
|
||||||
|
- Lock file: `Cargo.lock` ensures reproducible builds
|
||||||
|
- All dependencies from crates.io registry
|
||||||
|
- Transitive dependency management handled by Cargo
|
||||||
|
|
||||||
|
## Platform Requirements
|
||||||
|
|
||||||
|
**Development:**
|
||||||
|
- Rust toolchain (cargo)
|
||||||
|
- POSIX-compliant system (Linux, macOS) or Windows
|
||||||
|
- Terminal support for modern escape sequences
|
||||||
|
|
||||||
|
**Production:**
|
||||||
|
- Binary compiled for target platform (Linux, macOS, Windows)
|
||||||
|
- Terminal with VT100 escape sequence support
|
||||||
|
- UTF-8 capable terminal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Stack analysis: 2026-02-28*
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
# Codebase Structure
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-02-28
|
||||||
|
|
||||||
|
## Directory Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
bbs-md/
|
||||||
|
├── src/ # Rust source code
|
||||||
|
│ └── main.rs # Binary entry point and main application logic
|
||||||
|
├── target/ # Build artifacts (generated)
|
||||||
|
├── .git/ # Git repository metadata
|
||||||
|
├── .planning/ # Planning and documentation
|
||||||
|
│ └── codebase/ # Architecture and structure docs
|
||||||
|
├── Cargo.toml # Rust package manifest
|
||||||
|
├── Cargo.lock # Dependency lock file
|
||||||
|
└── .gitignore # Git ignore rules
|
||||||
|
```
|
||||||
|
|
||||||
|
## Directory Purposes
|
||||||
|
|
||||||
|
**src/**
|
||||||
|
- Purpose: All Rust source code for the project
|
||||||
|
- Contains: Rust modules and binary logic
|
||||||
|
- Key files: `main.rs`
|
||||||
|
|
||||||
|
**.planning/codebase/**
|
||||||
|
- Purpose: Architecture and codebase analysis documents
|
||||||
|
- Contains: ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md (as written)
|
||||||
|
- Generated by: Codebase mapping process
|
||||||
|
|
||||||
|
**target/**
|
||||||
|
- Purpose: Build output directory (generated by Cargo)
|
||||||
|
- Contains: Compiled binaries, dependencies, metadata
|
||||||
|
- Generated: Yes
|
||||||
|
- Committed: No (in .gitignore)
|
||||||
|
|
||||||
|
## Key File Locations
|
||||||
|
|
||||||
|
**Entry Points:**
|
||||||
|
- `src/main.rs`: Main binary executable, contains fn main() and all current application logic
|
||||||
|
|
||||||
|
**Configuration:**
|
||||||
|
- `Cargo.toml`: Package metadata, dependencies, build configuration
|
||||||
|
|
||||||
|
**Build Output:**
|
||||||
|
- `Cargo.lock`: Locked dependency versions ensuring reproducible builds
|
||||||
|
|
||||||
|
## Naming Conventions
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- `main.rs`: Entry point for binary crate
|
||||||
|
- `lib.rs`: Would be used for library crate (not present)
|
||||||
|
- Module files: `module_name.rs` (snake_case)
|
||||||
|
- Cargo files: `Cargo.toml`, `Cargo.lock`
|
||||||
|
|
||||||
|
**Directories:**
|
||||||
|
- `src/`: Source code directory (Rust convention)
|
||||||
|
- `target/`: Build output (Cargo convention)
|
||||||
|
- Module directories: `snake_case/` for organizing modules into subdirectories
|
||||||
|
|
||||||
|
**Modules:**
|
||||||
|
- Snake_case for module names in Rust
|
||||||
|
- Single-word module names preferred for clarity
|
||||||
|
|
||||||
|
## Where to Add New Code
|
||||||
|
|
||||||
|
**New Feature:**
|
||||||
|
- Primary code: `src/main.rs` until structure grows
|
||||||
|
- Once > 300 lines: Extract to `src/feature_name.rs`, then `mod feature_name;` in main.rs
|
||||||
|
- Tests: In same file with `#[cfg(test)]` module, or separate `src/feature_name_test.rs`
|
||||||
|
|
||||||
|
**New Component/Module:**
|
||||||
|
- Implementation: Create `src/module_name.rs`
|
||||||
|
- Export in `src/main.rs` with `mod module_name;`
|
||||||
|
- Public items: Use `pub` keyword and re-export in main if needed for internal use
|
||||||
|
|
||||||
|
**Utilities:**
|
||||||
|
- Shared helpers: Create `src/utils.rs` or `src/common.rs` for cross-cutting utilities
|
||||||
|
- General-purpose: Keep in dedicated module, expose via public functions
|
||||||
|
|
||||||
|
**UI Components:**
|
||||||
|
- Ratatui-specific code: Keep in dedicated module like `src/ui.rs` or `src/widgets.rs`
|
||||||
|
- Separate widget rendering logic from business logic
|
||||||
|
- Re-export commonly used widgets from central location
|
||||||
|
|
||||||
|
## Special Directories
|
||||||
|
|
||||||
|
**target/:**
|
||||||
|
- Purpose: Contains compiled binaries, intermediate build files, and dependencies
|
||||||
|
- Generated: Yes
|
||||||
|
- Committed: No
|
||||||
|
|
||||||
|
**.git/:**
|
||||||
|
- Purpose: Git repository metadata
|
||||||
|
- Generated: Yes
|
||||||
|
- Committed: Not applicable (part of .git directory)
|
||||||
|
|
||||||
|
## Recommended Module Organization (As Project Grows)
|
||||||
|
|
||||||
|
Once the codebase expands beyond the current single-file structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── main.rs # Binary entry, module declarations, main loop
|
||||||
|
├── app.rs # Application state and core logic
|
||||||
|
├── ui/
|
||||||
|
│ ├── mod.rs # UI module exports
|
||||||
|
│ ├── widgets.rs # Custom widget definitions
|
||||||
|
│ └── events.rs # Event handling logic
|
||||||
|
├── commands.rs # Command/action definitions
|
||||||
|
├── errors.rs # Error types
|
||||||
|
└── utils.rs # Utility functions
|
||||||
|
```
|
||||||
|
|
||||||
|
This structure keeps concerns separated while maintaining minimal interdependencies.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Structure analysis: 2026-02-28*
|
||||||
@@ -0,0 +1,324 @@
|
|||||||
|
# Testing Patterns
|
||||||
|
|
||||||
|
**Analysis Date:** 2026-02-28
|
||||||
|
|
||||||
|
## Test Framework
|
||||||
|
|
||||||
|
**Test Runner:**
|
||||||
|
- Rust built-in test framework (via `cargo test`)
|
||||||
|
- No external test framework currently integrated
|
||||||
|
- Can add `tokio` for async testing if needed later
|
||||||
|
|
||||||
|
**Assertion Library:**
|
||||||
|
- Standard `assert!()` and `assert_eq!()` macros from standard library
|
||||||
|
- Can add `pretty_assertions` crate for better failure output if desired
|
||||||
|
|
||||||
|
**Run Commands:**
|
||||||
|
```bash
|
||||||
|
cargo test # Run all tests
|
||||||
|
cargo test -- --nocapture # Run tests with output visible
|
||||||
|
cargo test -- --test-threads=1 # Run tests sequentially
|
||||||
|
cargo test --lib # Run only library tests
|
||||||
|
cargo test --doc # Run doctests
|
||||||
|
```
|
||||||
|
|
||||||
|
**Watch Mode:**
|
||||||
|
```bash
|
||||||
|
# Using cargo-watch (install with: cargo install cargo-watch)
|
||||||
|
cargo watch -x test # Re-run tests on file changes
|
||||||
|
```
|
||||||
|
|
||||||
|
**Coverage:**
|
||||||
|
```bash
|
||||||
|
# Using cargo-tarpaulin (install with: cargo install cargo-tarpaulin)
|
||||||
|
cargo tarpaulin --out Html # Generate HTML coverage report
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test File Organization
|
||||||
|
|
||||||
|
**Location - Unit Tests:**
|
||||||
|
- Co-located with implementation: Tests in same file as source code
|
||||||
|
- Tests go in submodule at end of source file
|
||||||
|
|
||||||
|
**Location - Integration Tests:**
|
||||||
|
- Separate `tests/` directory at workspace root
|
||||||
|
- File: `tests/integration_test.rs` or similar
|
||||||
|
- Each file is compiled as separate crate
|
||||||
|
|
||||||
|
**Naming:**
|
||||||
|
- Unit test modules: `#[cfg(test)] mod tests`
|
||||||
|
- Integration test files: `integration_test.rs`, `e2e_test.rs`
|
||||||
|
- Test functions: `test_function_name_description()`
|
||||||
|
- Unit tests: `tests::test_parses_valid_input()`
|
||||||
|
|
||||||
|
**Current Structure:**
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── main.rs # Contains #[cfg(test)] mod tests
|
||||||
|
├── lib.rs # If created, contains library tests
|
||||||
|
└── ...
|
||||||
|
|
||||||
|
tests/
|
||||||
|
├── integration_test.rs
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Structure
|
||||||
|
|
||||||
|
**Suite Organization - Unit Test Pattern:**
|
||||||
|
```rust
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_function_does_something() {
|
||||||
|
let input = setup_test_data();
|
||||||
|
let result = function_under_test(input);
|
||||||
|
assert_eq!(result, expected_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Suite Organization - Integration Test Pattern:**
|
||||||
|
```rust
|
||||||
|
// tests/integration_test.rs
|
||||||
|
#[test]
|
||||||
|
fn test_system_integrates_correctly() {
|
||||||
|
let app = App::new();
|
||||||
|
let result = app.process_command("help");
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Patterns:**
|
||||||
|
- **Setup:** Create test data or fixtures in test function body
|
||||||
|
- **Teardown:** Not typically needed in Rust; cleanup happens automatically when test scope ends
|
||||||
|
- **Assertion:** Use `assert!()`, `assert_eq!()`, `assert_ne!()` for conditions
|
||||||
|
|
||||||
|
## Mocking
|
||||||
|
|
||||||
|
**Framework:** No explicit mocking framework currently integrated
|
||||||
|
|
||||||
|
**If mocking becomes necessary:**
|
||||||
|
- Use `mockito` crate for HTTP mocking
|
||||||
|
- Use `mockall` crate for trait-based mocking
|
||||||
|
- Use `proptest` crate for property-based testing
|
||||||
|
|
||||||
|
**Current Approach:**
|
||||||
|
- Manual test doubles: Create simplified implementations of traits for testing
|
||||||
|
- Dependency injection: Pass different implementations at test time
|
||||||
|
- Stub data: Return hardcoded test data instead of external calls
|
||||||
|
|
||||||
|
**Example of Manual Test Double:**
|
||||||
|
```rust
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
struct MockDataStore {
|
||||||
|
data: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataStore for MockDataStore {
|
||||||
|
fn fetch(&self, id: u32) -> Option<String> {
|
||||||
|
self.data.get(id as usize).cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_with_mock() {
|
||||||
|
let mock = MockDataStore { data: vec!["test".to_string()] };
|
||||||
|
let result = process_data(&mock);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**What to Mock:**
|
||||||
|
- External service calls (network, file I/O)
|
||||||
|
- Database operations
|
||||||
|
- Time-dependent behavior
|
||||||
|
- Hardware-dependent code
|
||||||
|
|
||||||
|
**What NOT to Mock:**
|
||||||
|
- Core business logic
|
||||||
|
- Standard library functions
|
||||||
|
- Tested utility functions
|
||||||
|
- Pure functions
|
||||||
|
|
||||||
|
## Fixtures and Factories
|
||||||
|
|
||||||
|
**Test Data:**
|
||||||
|
- Currently: Manual test data created in test functions
|
||||||
|
- Pattern: Helper functions to build test objects
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```rust
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
fn create_test_user() -> User {
|
||||||
|
User {
|
||||||
|
id: 1,
|
||||||
|
name: "Test User".to_string(),
|
||||||
|
email: "test@example.com".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_user_creation() {
|
||||||
|
let user = create_test_user();
|
||||||
|
assert_eq!(user.name, "Test User");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Location:**
|
||||||
|
- Helper functions in same module as tests: `#[cfg(test)] mod tests`
|
||||||
|
- If many fixtures needed: Create `src/test_utils.rs` (not included in release build via `#[cfg(test)]`)
|
||||||
|
|
||||||
|
## Coverage
|
||||||
|
|
||||||
|
**Requirements:** Not currently enforced
|
||||||
|
|
||||||
|
**To Enable Coverage Tracking:**
|
||||||
|
```bash
|
||||||
|
# Using llvm-cov (install with: cargo install cargo-llvm-cov)
|
||||||
|
cargo llvm-cov # Generate coverage report
|
||||||
|
cargo llvm-cov --html # HTML report in target/llvm-cov/html
|
||||||
|
```
|
||||||
|
|
||||||
|
**Target for new code:**
|
||||||
|
- Aim for 80%+ coverage on public APIs
|
||||||
|
- 100% coverage on critical paths
|
||||||
|
- Document uncovered code with `#[cfg(test)]` or comments
|
||||||
|
|
||||||
|
## Test Types
|
||||||
|
|
||||||
|
**Unit Tests:**
|
||||||
|
- Scope: Single function or small module in isolation
|
||||||
|
- Approach: Test behavior with various inputs including edge cases
|
||||||
|
- Location: Same file as implementation in `#[cfg(test)] mod tests`
|
||||||
|
- Tools: Standard library assertions
|
||||||
|
|
||||||
|
**Integration Tests:**
|
||||||
|
- Scope: Multiple components working together
|
||||||
|
- Approach: Test workflows and interactions between modules
|
||||||
|
- Location: `tests/` directory at workspace root
|
||||||
|
- Tools: Standard library assertions
|
||||||
|
|
||||||
|
**Doc Tests:**
|
||||||
|
- Scope: Examples in `///` doc comments
|
||||||
|
- Approach: Verify example code actually works
|
||||||
|
- Location: Documentation strings in source
|
||||||
|
- Tools: Built-in `cargo test --doc`
|
||||||
|
|
||||||
|
**E2E Tests:**
|
||||||
|
- Currently: Not applicable (TUI application, no external API)
|
||||||
|
- When applicable: Test complete user workflows end-to-end
|
||||||
|
|
||||||
|
**Example Doc Test:**
|
||||||
|
```rust
|
||||||
|
/// Calculate the sum of two numbers.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// assert_eq!(add(2, 2), 4);
|
||||||
|
/// ```
|
||||||
|
pub fn add(a: i32, b: i32) -> i32 {
|
||||||
|
a + b
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
**Async Testing:**
|
||||||
|
- Not currently used (no async in codebase)
|
||||||
|
- When needed: Use `#[tokio::test]` attribute with `tokio` crate
|
||||||
|
|
||||||
|
**Example (future reference):**
|
||||||
|
```rust
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_async_function() {
|
||||||
|
let result = async_operation().await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Error Testing:**
|
||||||
|
- Test both success and failure paths
|
||||||
|
- Use `.is_err()` or `.is_ok()` to test Result types
|
||||||
|
- Use `.is_some()` or `.is_none()` to test Option types
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```rust
|
||||||
|
#[test]
|
||||||
|
fn test_handles_invalid_input() {
|
||||||
|
let result = parse_config("invalid");
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_handles_valid_input() {
|
||||||
|
let result = parse_config("valid");
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Property-Based Testing (future):**
|
||||||
|
If using `proptest`:
|
||||||
|
```rust
|
||||||
|
#[test]
|
||||||
|
fn test_reverse_is_involutive(input in ".*") {
|
||||||
|
let reversed = reverse(&input);
|
||||||
|
let double_reversed = reverse(&reversed);
|
||||||
|
assert_eq!(input, double_reversed);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Organization Best Practices
|
||||||
|
|
||||||
|
**File Structure:**
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── main.rs
|
||||||
|
├── ui.rs # Contains #[cfg(test)] mod tests at bottom
|
||||||
|
├── handler.rs # Contains #[cfg(test)] mod tests at bottom
|
||||||
|
└── model.rs # Contains #[cfg(test)] mod tests at bottom
|
||||||
|
|
||||||
|
tests/
|
||||||
|
├── integration_tests.rs # Full-system integration tests
|
||||||
|
└── fixtures/ # Test data files if needed
|
||||||
|
```
|
||||||
|
|
||||||
|
**Test Module Template:**
|
||||||
|
```rust
|
||||||
|
// At end of source file
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// Setup helpers
|
||||||
|
fn create_test_fixture() -> TestData {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests organized by function
|
||||||
|
mod function_name_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_success_case() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_error_case() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Testing analysis: 2026-02-28*
|
||||||
Reference in New Issue
Block a user