diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..517f17a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,101 @@ +name: Bug Report +description: File a bug report to help us improve QuickCodes +title: "[Bug]: " +labels: ["bug", "needs-triage"] +assignees: ["marcioreck"] + +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug! Please fill out this form as completely as possible. + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear and concise description of the bug + placeholder: Describe what happened and what you expected to happen + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to Reproduce + description: Detailed steps to reproduce the bug + placeholder: | + 1. Install QuickCodes with `cargo add quickcodes` + 2. Run the following code... + 3. Observe the error... + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What did you expect to happen? + placeholder: Describe the expected behavior + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What actually happened? + placeholder: Describe what actually happened, include error messages + validations: + required: true + + - type: textarea + id: environment + attributes: + label: Environment + description: Information about your environment + placeholder: | + - OS: [e.g., Ubuntu 22.04, macOS 13.0, Windows 11] + - Rust version: [e.g., 1.75.0] + - QuickCodes version: [e.g., 0.1.0] + - Features enabled: [e.g., png, svg, python] + validations: + required: true + + - type: textarea + id: code + attributes: + label: Code Sample + description: Minimal code sample that reproduces the issue + render: rust + placeholder: | + use quickcodes::{generate, BarcodeType, ExportFormat}; + + fn main() { + // Your code that reproduces the bug + } + validations: + required: false + + - type: textarea + id: logs + attributes: + label: Error Logs + description: Any relevant error logs or output + render: text + placeholder: Paste error logs here (if any) + validations: + required: false + + - type: checkboxes + id: checklist + attributes: + label: Checklist + description: Please confirm the following + options: + - label: I have searched existing issues to ensure this bug hasn't been reported + required: true + - label: I have tested with the latest version of QuickCodes + required: true + - label: I have provided a minimal code sample that reproduces the issue + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..02e0dd1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,114 @@ +name: Feature Request +description: Suggest a new feature or enhancement for QuickCodes +title: "[Feature]: " +labels: ["enhancement", "needs-triage"] +assignees: ["marcioreck"] + +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a new feature! Please help us understand your needs. + + - type: textarea + id: feature-description + attributes: + label: Feature Description + description: A clear and concise description of the feature you'd like to see + placeholder: Describe the feature you want to add + validations: + required: true + + - type: textarea + id: use-case + attributes: + label: Use Case + description: Describe the problem this feature would solve + placeholder: | + What problem does this feature solve? + How would you use this feature? + Who would benefit from this feature? + validations: + required: true + + - type: textarea + id: proposed-solution + attributes: + label: Proposed Solution + description: How do you think this feature should work? + placeholder: Describe your proposed solution in detail + validations: + required: true + + - type: textarea + id: api-design + attributes: + label: Proposed API Design + description: If applicable, show how the API might look + render: rust + placeholder: | + // Example of how the new API might work + use quickcodes::*; + + let result = new_feature_function(parameters); + validations: + required: false + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: What alternative solutions have you considered? + placeholder: Describe any alternative approaches you've considered + validations: + required: false + + - type: dropdown + id: priority + attributes: + label: Priority + description: How important is this feature to you? + options: + - "Low - Nice to have" + - "Medium - Would be helpful" + - "High - Important for my use case" + - "Critical - Blocking my project" + validations: + required: true + + - type: dropdown + id: complexity + attributes: + label: Implementation Complexity + description: How complex do you think this feature would be to implement? + options: + - "Simple - Minor change" + - "Medium - Moderate effort" + - "Complex - Significant development" + - "I'm not sure" + validations: + required: false + + - type: checkboxes + id: implementation + attributes: + label: Implementation + description: Are you willing to contribute to implementing this feature? + options: + - label: I'm willing to implement this feature myself + - label: I can help with testing and feedback + - label: I can help with documentation + - label: I would like someone else to implement this + + - type: checkboxes + id: checklist + attributes: + label: Checklist + description: Please confirm the following + options: + - label: I have searched existing issues and feature requests + required: true + - label: This feature aligns with QuickCodes' goals of barcode/QR generation + required: true + - label: I have provided a clear use case for this feature + required: true \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0b9c70c..5f2a1d1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,6 +5,8 @@ updates: directory: "/" schedule: interval: "weekly" + day: "monday" + time: "09:00" open-pull-requests-limit: 10 reviewers: - "marcioreck" @@ -13,12 +15,25 @@ updates: commit-message: prefix: "deps" include: "scope" + # Allow security updates to be auto-merged + allow: + - dependency-type: "direct" + update-type: "security" + - dependency-type: "indirect" + update-type: "security" + # Ignore specific dependencies if needed + ignore: + # Example: ignore major version updates for stable dependencies + # - dependency-name: "serde" + # update-types: ["version-update:semver-major"] # Enable version updates for GitHub Actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" + day: "monday" + time: "09:00" open-pull-requests-limit: 5 reviewers: - "marcioreck" @@ -27,3 +42,28 @@ updates: commit-message: prefix: "ci" include: "scope" + # Auto-merge minor and patch updates for GitHub Actions + allow: + - dependency-type: "direct" + update-type: "security" + - dependency-type: "direct" + update-type: "minor" + - dependency-type: "direct" + update-type: "patch" + + # Python dependencies (for Python bindings) + - package-ecosystem: "pip" + directory: "/python" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + reviewers: + - "marcioreck" + assignees: + - "marcioreck" + commit-message: + prefix: "deps(python)" + include: "scope" + allow: + - dependency-type: "direct" + update-type: "security" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..758c107 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,85 @@ +## Summary + + + +## Type of Change + + + +- [ ] Bug fix (non-breaking change that fixes an issue) +- [ ] New feature (non-breaking change that adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation update +- [ ] Code quality improvement +- [ ] Performance improvement +- [ ] Test improvement + +## Changes Made + + + +- +- +- + +## Testing + + + +- [ ] All existing tests pass +- [ ] New tests added for new functionality +- [ ] Manual testing performed +- [ ] Examples updated and tested + +**Test Details:** + + +## Documentation + + + +- [ ] Code comments updated +- [ ] README.md updated +- [ ] CHANGELOG.md updated +- [ ] API documentation updated +- [ ] Examples updated +- [ ] No documentation changes needed + +## Breaking Changes + + + +**None** OR **Describe breaking changes:** + +## Checklist + + + +- [ ] My code follows the project's style guidelines +- [ ] I have performed a self-review of my code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published + +## Related Issues + + + +Fixes #(issue_number) +Closes #(issue_number) +Related to #(issue_number) + +## Additional Notes + + + +## Review Focus + + + +- +- +- \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1cc3e6d..b2a4f18 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: run: cargo fmt --all -- --check - name: Clippy - run: cargo clippy --all-targets --features "png,svg" -- -D warnings + run: cargo clippy --all-targets --features "png,svg" -- -D warnings -A clippy::needless_range_loop -A clippy::collapsible_if -A clippy::incompatible_msrv # Testes em múltiplas plataformas e versões do Rust test: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..bb832ea --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,54 @@ +name: "CodeQL Security Analysis" + +on: + push: + branches: [ "main", "develop" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '0 2 * * 1' # Weekly on Monday at 2 AM UTC + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'rust' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # Override the default queries + queries: +security-and-quality + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Build project + run: cargo build --verbose + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" \ No newline at end of file diff --git a/.gitignore b/.gitignore index ea8c4bf..c37da39 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,97 @@ -/target +# Rust build artifacts +/target/ +Cargo.lock + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS specific files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Python artifacts (for Python bindings) +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Virtual environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Generated documentation +doc/ +docs/_build/ + +# Test artifacts +.coverage +htmlcov/ +.tox/ +.pytest_cache/ + +# Generated examples output +examples/output/*.png +examples/output/*.svg +examples/output/*.jpg +examples/output/*.jpeg + +# Temporary files +*.tmp +*.temp +/tmp/ + +# Log files +*.log + +# Security and secrets +.env.local +.env.production +secrets.toml + +# Benchmark results +criterion/ + +# Profiling data +*.prof + +# Node.js (for future JavaScript bindings) +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Coverage reports +tarpaulin-report.html +coverage.xml +lcov.info diff --git a/RULESETS.md b/RULESETS.md new file mode 100644 index 0000000..ff14c3c --- /dev/null +++ b/RULESETS.md @@ -0,0 +1,114 @@ +# QuickCodes Repository Rulesets + +This document outlines the basic rulesets and policies for the QuickCodes repository to ensure code quality, security, and maintainable development practices. + +## Branch Protection Rules + +### Main Branch (`main`) +- **Required status checks**: All CI checks must pass + - Code formatting (`cargo fmt --check`) + - Linting (`cargo clippy`) + - Tests (unit, integration, doc tests) + - Security audit (`cargo audit`) + - Cross-platform compatibility (Linux, Windows, macOS) +- **Require branches to be up to date**: Yes +- **Required reviews**: At least 1 approval required +- **Dismiss stale reviews**: Yes +- **Require review from code owners**: Yes +- **Restrict pushes**: Only allow pull requests +- **Force push restrictions**: Not allowed +- **Deletion restrictions**: Not allowed + +### Development Branch (`develop`) +- **Required status checks**: Basic CI checks +- **Required reviews**: At least 1 approval for external contributors +- **Allow force pushes**: Only for maintainers + +## Code Quality Rules + +### Required Checks +1. **Formatting**: `cargo fmt --check` must pass +2. **Linting**: `cargo clippy --all-targets --all-features -- -D warnings` must pass +3. **Testing**: All tests must pass (unit, integration, doc tests) +4. **Documentation**: Public APIs must have documentation +5. **Security**: `cargo audit` must pass +6. **Dependencies**: Dependabot security updates + +### Code Standards +- Follow Rust standard formatting (configured in `rustfmt.toml`) +- Address all clippy warnings (configured in `clippy.toml`) +- Maintain test coverage above 90% +- Use conventional commit messages +- Include examples in documentation + +## Security Rules + +### Dependency Management +- **Automated updates**: Dependabot enabled for weekly updates +- **Security scanning**: Cargo audit in CI pipeline +- **Vulnerability alerts**: Enabled for all dependencies +- **Private vulnerability reporting**: Enabled + +### Secret Management +- **No secrets in code**: Use environment variables or secret management +- **Credential scanning**: Automated detection of exposed credentials +- **API keys**: Store in repository secrets for CI/CD + +## Pull Request Requirements + +### Required Information +1. **Clear description**: What changes were made and why +2. **Breaking changes**: Clearly marked if any +3. **Testing**: Evidence that changes were tested +4. **Documentation**: Updated if public APIs changed +5. **Changelog**: Updated for user-facing changes + +### Review Process +1. **Automated checks**: All CI checks must pass +2. **Manual review**: At least one maintainer approval +3. **Code owner review**: For core functionality changes +4. **Integration testing**: Verify examples still work + +## Release Rules + +### Version Management +- **Semantic versioning**: Follow semver strictly +- **Changelog**: Update CHANGELOG.md for all releases +- **Git tags**: All releases must be tagged +- **Release notes**: Generated automatically from changelog + +### Release Process +1. **Update version**: In Cargo.toml and related files +2. **Update changelog**: Document all changes +3. **Create PR**: For release preparation +4. **Tag release**: After merge to main +5. **Publish**: Automated via CI/CD to crates.io + +## Issue and Project Management + +### Issue Templates +- **Bug reports**: Require reproduction steps and environment details +- **Feature requests**: Require use case and proposed implementation +- **Security issues**: Private reporting enabled + +### Labels and Milestones +- **Priority levels**: P0 (critical), P1 (high), P2 (medium), P3 (low) +- **Component labels**: Core, Python bindings, Examples, Documentation +- **Status tracking**: In progress, under review, blocked + +## Enforcement + +These rules are enforced through: +1. **GitHub branch protection**: Prevents direct pushes to protected branches +2. **CI/CD pipeline**: Automated quality checks +3. **Required reviews**: Human oversight for all changes +4. **Automated tooling**: Dependabot, security scanning, formatting checks + +## Exceptions + +Exceptions to these rules may be granted by repository maintainers in the following cases: +- **Emergency security fixes**: May bypass some review requirements +- **Critical bug fixes**: May be fast-tracked with reduced review time +- **Documentation-only changes**: May have relaxed requirements + +All exceptions must be documented and justified in the pull request. \ No newline at end of file diff --git a/RULESETS_GUIDE.md b/RULESETS_GUIDE.md new file mode 100644 index 0000000..40dbee9 --- /dev/null +++ b/RULESETS_GUIDE.md @@ -0,0 +1,248 @@ +# QuickCodes Rulesets Setup Guide + +This document provides a comprehensive guide for setting up and maintaining the basic rulesets for the QuickCodes project. These rulesets ensure code quality, security, and consistent development practices. + +## Overview + +The QuickCodes project uses a multi-layered approach to enforce quality and security standards: + +1. **Code Quality Tools**: rustfmt, clippy, cargo audit +2. **GitHub Features**: Branch protection, pull request templates, issue templates +3. **CI/CD Pipeline**: Automated testing, security scanning, cross-platform verification +4. **Dependency Management**: Dependabot for automated updates +5. **Security**: CodeQL analysis, vulnerability reporting + +## Files Added/Modified + +### Configuration Files + +- **`rustfmt.toml`**: Rust code formatting configuration +- **`clippy.toml`**: Clippy linting configuration +- **`.gitignore`**: Enhanced to exclude build artifacts and temporary files +- **`RULESETS.md`**: Repository ruleset documentation +- **`SECURITY.md`**: Security policy and vulnerability reporting + +### GitHub Templates + +- **`.github/ISSUE_TEMPLATE/bug_report.yml`**: Structured bug report template +- **`.github/ISSUE_TEMPLATE/feature_request.yml`**: Feature request template +- **`.github/pull_request_template.md`**: Pull request template + +### Workflow Files + +- **`.github/workflows/codeql.yml`**: CodeQL security analysis +- **`.github/dependabot.yml`**: Enhanced dependency management + +## Ruleset Components + +### 1. Code Quality Standards + +#### Formatting (rustfmt) +```bash +# Check formatting +cargo fmt --check + +# Apply formatting +cargo fmt +``` + +**Configuration in `rustfmt.toml`:** +- Max line width: 100 characters +- Unix-style line endings +- 4-space indentation +- Reorder imports automatically + +#### Linting (clippy) +```bash +# Run clippy with project-specific rules +cargo clippy --all-targets --features "png,svg" -- -D warnings -A clippy::needless_range_loop -A clippy::collapsible_if -A clippy::incompatible_msrv +``` + +**Configuration in `clippy.toml`:** +- Cognitive complexity threshold: 25 +- Type complexity threshold: 100 +- Maximum arguments: 8 +- MSRV: 1.70.0 + +### 2. Branch Protection Rules + +#### Main Branch (`main`) +- **Required Checks**: All CI jobs must pass +- **Required Reviews**: Minimum 1 approval +- **Up-to-date requirement**: Branch must be current +- **Force push**: Disabled +- **Deletion**: Disabled + +#### Development Branch (`develop`) +- **Basic CI checks**: Required +- **Review requirement**: 1 approval for external contributors +- **Force push**: Maintainers only + +### 3. Security Measures + +#### Automated Security Scanning +- **CodeQL**: Weekly security analysis +- **Cargo Audit**: Dependency vulnerability scanning +- **Dependabot**: Weekly dependency updates + +#### Vulnerability Reporting +- **Private reporting**: Enabled via GitHub Security tab +- **Response timeline**: 48 hours acknowledgment, 7 days detailed response +- **Disclosure policy**: Coordinated disclosure after fix + +### 4. Issue and PR Management + +#### Issue Templates +- **Bug reports**: Structured with reproduction steps, environment details +- **Feature requests**: Include use case, proposed API, implementation complexity + +#### Pull Request Requirements +- **Description**: Clear summary of changes +- **Testing**: Evidence of testing +- **Documentation**: Updated if APIs changed +- **Breaking changes**: Clearly marked +- **Checklist**: Quality assurance items + +## Setting Up the Rulesets + +### 1. Repository Settings + +To fully implement these rulesets, repository administrators should: + +#### Branch Protection Rules +1. Go to Settings → Branches +2. Add protection rule for `main`: + ``` + - Require status checks: ✓ + - Require branches to be up to date: ✓ + - Required status checks: check, test, coverage, security + - Require pull request reviews: ✓ + - Required approving reviewers: 1 + - Dismiss stale reviews: ✓ + - Restrict pushes to matching branches: ✓ + - Allow force pushes: ✗ + - Allow deletions: ✗ + ``` + +#### Security Settings +1. Go to Settings → Security & analysis +2. Enable: + - Dependency graph + - Dependabot alerts + - Dependabot security updates + - Code scanning (CodeQL) + - Secret scanning + +### 2. Required Secrets + +Add these secrets in Settings → Secrets and variables → Actions: +- `CODECOV_TOKEN`: For code coverage reporting +- `CARGO_REGISTRY_TOKEN`: For automated publishing (if needed) + +### 3. Local Development Setup + +Developers should: + +1. **Install Rust tools**: + ```bash + rustup component add rustfmt clippy + cargo install cargo-audit + ``` + +2. **Pre-commit hooks** (optional but recommended): + ```bash + # Add to .git/hooks/pre-commit + #!/bin/sh + cargo fmt --check || exit 1 + cargo clippy --all-targets --all-features -- -D warnings -A clippy::needless_range_loop -A clippy::collapsible_if -A clippy::incompatible_msrv || exit 1 + cargo test --all || exit 1 + ``` + +## Enforcement Mechanisms + +### Automated Enforcement +- **CI/CD Pipeline**: Prevents merging of non-compliant code +- **Branch protection**: Enforces review and status check requirements +- **Dependabot**: Automatically creates PRs for security updates + +### Human Review Process +- **Code owners**: Automatic review assignment for core changes +- **Pull request templates**: Ensure complete information +- **Issue templates**: Standardize bug reports and feature requests + +## Monitoring and Maintenance + +### Weekly Tasks +- Review Dependabot PRs +- Check security alerts +- Monitor CI/CD performance + +### Monthly Tasks +- Review and update ruleset documentation +- Analyze code coverage trends +- Update issue/PR templates if needed + +### Quarterly Tasks +- Review MSRV compatibility +- Update clippy configuration +- Assess security posture + +## Customization Guidelines + +### Adding New Rules +1. Update appropriate configuration file (`clippy.toml`, `rustfmt.toml`) +2. Test changes locally +3. Update CI workflows if necessary +4. Document changes in this guide + +### Exemptions Process +1. Create issue describing why exemption is needed +2. Get approval from maintainers +3. Document exemption reason +4. Set time limit for review + +### Tool Updates +1. Test tool updates in development branch +2. Update CI workflows +3. Update local development instructions +4. Communicate changes to team + +## Troubleshooting + +### Common Issues + +#### Clippy Failures +```bash +# Check specific lint +cargo clippy --all-targets -- -W clippy::specific_lint + +# Allow specific lint temporarily +cargo clippy --all-targets -- -A clippy::specific_lint +``` + +#### Formatting Issues +```bash +# See what would change +cargo fmt --check + +# Apply all formatting +cargo fmt +``` + +#### CI Failures +- Check if all required secrets are set +- Verify branch protection rules are correctly configured +- Ensure all required status checks are defined + +### Getting Help + +- **Issues**: Use the bug report template +- **Discussions**: For questions about rulesets +- **Security**: Use private vulnerability reporting +- **Urgent**: Contact maintainers directly + +## Conclusion + +These rulesets provide a comprehensive foundation for maintaining code quality and security in the QuickCodes project. They balance automation with human oversight to ensure consistent, secure, and maintainable code. + +Regular review and updates of these rules ensure they continue to serve the project's evolving needs while maintaining high standards for contributors and users. \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..1ff0f63 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,93 @@ +# Security Policy + +## Supported Versions + +We actively support the following versions of QuickCodes with security updates: + +| Version | Supported | +| ------- | ------------------ | +| 0.1.x | :white_check_mark: | +| < 0.1 | :x: | + +## Reporting a Vulnerability + +We take security vulnerabilities seriously. If you discover a security vulnerability in QuickCodes, please report it responsibly. + +### Private Reporting + +For security vulnerabilities, please use GitHub's private vulnerability reporting feature: + +1. Go to the [QuickCodes repository](https://github.com/marcioreck/quickcodes) +2. Click on the "Security" tab +3. Click "Report a vulnerability" +4. Provide detailed information about the vulnerability + +### What to Include + +Please include the following information in your report: + +- **Description**: Clear description of the vulnerability +- **Impact**: Potential impact and severity assessment +- **Reproduction**: Step-by-step instructions to reproduce the issue +- **Environment**: Rust version, operating system, and QuickCodes version +- **Proposed fix**: If you have suggestions for fixing the vulnerability + +### Response Timeline + +We will acknowledge receipt of your vulnerability report within **48 hours** and provide a detailed response within **7 days** indicating: + +- Confirmation of the vulnerability +- Our assessment of its impact and severity +- Timeline for developing and releasing a fix +- Whether public disclosure is appropriate + +### Disclosure Policy + +- We will work with you to understand the scope and impact of the vulnerability +- We will develop a fix and coordinate the release timeline with you +- We will publicly disclose the vulnerability after a fix is available +- We will credit you for responsible disclosure (unless you prefer to remain anonymous) + +### Security Best Practices + +When using QuickCodes, please follow these security best practices: + +1. **Keep dependencies updated**: Regularly update QuickCodes and its dependencies +2. **Validate input data**: Always validate and sanitize input data before generating barcodes +3. **Error handling**: Properly handle errors and don't expose sensitive information +4. **Audit dependencies**: Use `cargo audit` to check for known vulnerabilities +5. **Secure deployment**: Follow secure coding practices in your applications + +### Security Features + +QuickCodes includes the following security features: + +- **Input validation**: Comprehensive validation of input data +- **Error handling**: Safe error handling without information leakage +- **Memory safety**: Built with Rust for memory safety guarantees +- **Dependency management**: Regular automated dependency updates via Dependabot +- **CI/CD security**: Automated security scanning in our build pipeline + +### Known Security Considerations + +- **Input size limits**: Very large input data may cause memory issues +- **Resource consumption**: Complex barcodes may consume significant CPU/memory +- **Output validation**: Generated barcodes should be validated in production systems + +### Contact Information + +For non-security issues, please use our regular issue tracker: +- **Issues**: https://github.com/marcioreck/quickcodes/issues +- **Discussions**: https://github.com/marcioreck/quickcodes/discussions + +For urgent security matters, you can also contact: +- **Email**: marcio@fazmercado.com (please include "QuickCodes Security" in subject) + +## Security Updates + +Security updates will be released as patch versions and will be clearly marked in: +- Release notes +- CHANGELOG.md +- Security advisories + +We recommend enabling GitHub's dependency alerts and security updates for your projects using QuickCodes. \ No newline at end of file diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..64977ea --- /dev/null +++ b/clippy.toml @@ -0,0 +1,21 @@ +# Clippy configuration for QuickCodes +# This file defines linting rules for consistent code quality + +# Complexity thresholds +cognitive-complexity-threshold = 25 +type-complexity-threshold = 100 +too-many-arguments-threshold = 8 +too-many-lines-threshold = 150 + +# Allow certain types and methods that are commonly used +disallowed-methods = [] +disallowed-types = [] + +# Documentation requirements +missing-docs-in-crate-items = true + +# Avoid certain constructs +avoid-breaking-exported-api = true + +# MSRV compatibility +msrv = "1.70.0" \ No newline at end of file diff --git a/examples/phase2_usage.rs b/examples/phase2_usage.rs index 6b8636c..d5d50fe 100644 --- a/examples/phase2_usage.rs +++ b/examples/phase2_usage.rs @@ -1,5 +1,5 @@ //! Phase 2 Usage Examples -//! +//! //! This example demonstrates the new advanced 2D barcode formats //! introduced in Phase 2: DataMatrix, PDF417, and Aztec Code. diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..386ba53 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,17 @@ +# Rust formatting configuration for QuickCodes +# This ensures consistent code formatting across the project + +# Basic formatting +max_width = 100 +hard_tabs = false +tab_spaces = 4 + +# Import formatting +reorder_imports = true + +# Code style +newline_style = "Unix" +edition = "2021" + +# Misc +use_small_heuristics = "Default" \ No newline at end of file diff --git a/src/generators/aztec.rs b/src/generators/aztec.rs index 8360a56..37489c9 100644 --- a/src/generators/aztec.rs +++ b/src/generators/aztec.rs @@ -1,11 +1,9 @@ //! Aztec Code generator -//! +//! //! Aztec Code is a 2D barcode commonly used in transportation tickets, //! particularly in Europe and for mobile ticketing applications. -use crate::types::{ - Barcode, BarcodeConfig, BarcodeModules, BarcodeType, QuickCodesError, Result, -}; +use crate::types::{Barcode, BarcodeConfig, BarcodeModules, BarcodeType, QuickCodesError, Result}; /// Aztec Code configuration options #[derive(Debug, Clone)] @@ -23,7 +21,7 @@ impl Default for AztecConfig { Self { compact: false, error_correction: 23, // ~23% error correction - layers: None, // Auto-select + layers: None, // Auto-select } } } @@ -62,7 +60,9 @@ fn generate_aztec_matrix(data: &str, config: &AztecConfig) -> Result Result], size: usize) { let center = size / 2; - + // Create concentric squares (simplified bullseye pattern) for ring in 0..=5 { let is_filled = ring % 2 == 1; let start = center.saturating_sub(ring); let end = (center + ring + 1).min(size); - + for y in start..end { for x in start..end { if y == start || y == end - 1 || x == start || x == end - 1 { @@ -124,31 +124,31 @@ fn generate_reference_grid(matrix: &mut [Vec], size: usize) { fn encode_data_spiral(matrix: &mut [Vec], data: &[u8], size: usize, compact: bool) { let start_radius = if compact { 6 } else { 8 }; let center = size / 2; - + let mut bit_index = 0; let total_bits = data.len() * 8; - + // Spiral outward from center for radius in start_radius..center { let positions = get_spiral_positions(center, radius, size); - + for (x, y) in positions { if bit_index >= total_bits { break; } - + // Skip finder pattern and reference grid positions if is_data_position(x, y, center, compact) { let byte_idx = bit_index / 8; let bit_pos = 7 - (bit_index % 8); - + if byte_idx < data.len() { matrix[y][x] = (data[byte_idx] >> bit_pos) & 1 == 1; bit_index += 1; } } } - + if bit_index >= total_bits { break; } @@ -160,21 +160,21 @@ fn get_spiral_positions(center: usize, radius: usize, size: usize) -> Vec<(usize let mut positions = Vec::new(); let start = center.saturating_sub(radius); let end = (center + radius + 1).min(size); - + // Top row for x in start..end { if start < size { positions.push((x, start)); } } - + // Right column for y in (start + 1)..end { if end > 0 && end - 1 < size && y < size { positions.push((end - 1, y)); } } - + // Bottom row (if different from top) if end > start + 1 { for x in (start..(end - 1)).rev() { @@ -183,7 +183,7 @@ fn get_spiral_positions(center: usize, radius: usize, size: usize) -> Vec<(usize } } } - + // Left column (if different from right) if end > start + 1 { for y in ((start + 1)..(end - 1)).rev() { @@ -192,25 +192,25 @@ fn get_spiral_positions(center: usize, radius: usize, size: usize) -> Vec<(usize } } } - + positions } /// Check if position is available for data (not finder pattern or reference grid) fn is_data_position(x: usize, y: usize, center: usize, compact: bool) -> bool { - let dx = (x as i32 - center as i32).abs() as usize; - let dy = (y as i32 - center as i32).abs() as usize; - + let dx = (x as i32 - center as i32).unsigned_abs(); + let dy = (y as i32 - center as i32).unsigned_abs(); + // Skip finder pattern area if dx <= 5 && dy <= 5 { return false; } - + // Skip reference grid for full format if !compact && (x % 16 == 0 || y % 16 == 0) { return false; } - + true } @@ -219,7 +219,7 @@ fn calculate_layers(data_len: usize, compact: bool) -> u8 { // Simplified calculation - real Aztec uses complex capacity tables let bits_needed = data_len * 8; let max_layers = if compact { 4 } else { 32 }; - + for layer in 1..=max_layers { let capacity = if compact { // Compact capacity approximation @@ -228,12 +228,12 @@ fn calculate_layers(data_len: usize, compact: bool) -> u8 { // Full capacity approximation layer as usize * 256 // Rough estimate }; - + if capacity >= bits_needed { return layer; } } - + max_layers } @@ -287,19 +287,35 @@ mod tests { let result2 = calculate_layers(100, true); let result3 = calculate_layers(10, false); let result4 = calculate_layers(1000, false); - + // Verify they are within valid ranges - assert!(result1 >= 1 && result1 <= 4, "Compact layers should be 1-4, got {}", result1); - assert!(result2 >= 1 && result2 <= 4, "Compact layers should be 1-4, got {}", result2); - assert!(result3 >= 1 && result3 <= 32, "Full layers should be 1-32, got {}", result3); - assert!(result4 >= 1 && result4 <= 32, "Full layers should be 1-32, got {}", result4); + assert!( + (1..=4).contains(&result1), + "Compact layers should be 1-4, got {}", + result1 + ); + assert!( + (1..=4).contains(&result2), + "Compact layers should be 1-4, got {}", + result2 + ); + assert!( + (1..=32).contains(&result3), + "Full layers should be 1-32, got {}", + result3 + ); + assert!( + (1..=32).contains(&result4), + "Full layers should be 1-32, got {}", + result4 + ); } #[test] fn test_finder_pattern() { let mut matrix = vec![vec![false; 21]; 21]; generate_finder_pattern(&mut matrix, 21); - + // Check that center has some pattern let center = 10; let mut has_pattern = false; @@ -311,6 +327,9 @@ mod tests { } } } - assert!(has_pattern, "Finder pattern should have some filled modules"); + assert!( + has_pattern, + "Finder pattern should have some filled modules" + ); } } diff --git a/src/generators/datamatrix.rs b/src/generators/datamatrix.rs index 0d9bbb0..24f4315 100644 --- a/src/generators/datamatrix.rs +++ b/src/generators/datamatrix.rs @@ -1,14 +1,12 @@ //! DataMatrix barcode generator -//! +//! //! DataMatrix is a 2D barcode commonly used in pharmaceutical and industrial applications. //! It's particularly important for ANVISA compliance in Brazil. -//! +//! //! This is a simplified implementation for demonstration purposes. //! A production implementation would use proper DataMatrix encoding algorithms. -use crate::types::{ - Barcode, BarcodeConfig, BarcodeModules, BarcodeType, QuickCodesError, Result, -}; +use crate::types::{Barcode, BarcodeConfig, BarcodeModules, BarcodeType, QuickCodesError, Result}; /// Generate a DataMatrix with default configuration pub fn generate_datamatrix(data: &str) -> Result { @@ -46,7 +44,7 @@ fn generate_datamatrix_pattern(data: &str) -> Result>> { // 4. Module placement algorithm let data_bytes = data.as_bytes(); - + // Calculate size based on data length (simplified) let size = calculate_datamatrix_size(data_bytes.len()); let mut matrix = vec![vec![false; size]; size]; @@ -84,17 +82,17 @@ fn generate_finder_patterns(matrix: &mut [Vec], size: usize) { for y in 0..size { matrix[y][0] = true; } - + // Bottom border (solid line) for x in 0..size { matrix[size - 1][x] = true; } - + // Top border (alternating pattern) for x in (0..size).step_by(2) { matrix[0][x] = true; } - + // Right border (alternating pattern) for y in (1..size).step_by(2) { matrix[y][size - 1] = true; @@ -105,18 +103,18 @@ fn generate_finder_patterns(matrix: &mut [Vec], size: usize) { fn fill_data_area(matrix: &mut [Vec], data: &[u8], size: usize) { let mut bit_index = 0; let total_bits = data.len() * 8; - + // Fill in a diagonal pattern (simplified placement algorithm) for diagonal in 0..(size * 2) { for i in 0..=diagonal { let x = i; let y = diagonal - i; - + if x < size && y < size && x > 0 && y > 0 && x < size - 1 && y < size - 1 { if bit_index < total_bits { let byte_idx = bit_index / 8; let bit_pos = 7 - (bit_index % 8); - + if byte_idx < data.len() { matrix[y][x] = (data[byte_idx] >> bit_pos) & 1 == 1; bit_index += 1; diff --git a/src/generators/mod.rs b/src/generators/mod.rs index 8f272d4..a271622 100644 --- a/src/generators/mod.rs +++ b/src/generators/mod.rs @@ -6,9 +6,9 @@ pub mod qr; pub mod upc; // Phase 2: Advanced 2D codes +pub mod aztec; pub mod datamatrix; pub mod pdf417; -pub mod aztec; // Re-export generator functions pub use code128::generate_code128; @@ -17,6 +17,6 @@ pub use qr::generate_qr; pub use upc::generate_upc_a; // Phase 2 generators +pub use aztec::generate_aztec; pub use datamatrix::generate_datamatrix; pub use pdf417::generate_pdf417; -pub use aztec::generate_aztec; diff --git a/src/generators/pdf417.rs b/src/generators/pdf417.rs index 4fb86cb..a4e2f5e 100644 --- a/src/generators/pdf417.rs +++ b/src/generators/pdf417.rs @@ -1,11 +1,9 @@ //! PDF417 barcode generator -//! +//! //! PDF417 is a stacked linear barcode commonly used in official documents, //! driver's licenses, and identification cards. -use crate::types::{ - Barcode, BarcodeConfig, BarcodeModules, BarcodeType, QuickCodesError, Result, -}; +use crate::types::{Barcode, BarcodeConfig, BarcodeModules, BarcodeType, QuickCodesError, Result}; /// PDF417 configuration options #[derive(Debug, Clone)] @@ -64,7 +62,11 @@ fn generate_pdf417_matrix(data: &str, config: &PDF417Config) -> Result Result> (7 - bit_idx)) & 1 == 1; } else { @@ -117,10 +119,10 @@ fn calculate_rows(data_len: usize, columns: usize, error_level: u8) -> usize { }; let total_codewords = data_len + error_codewords + 1; // +1 for length indicator - let rows = (total_codewords + columns - 1) / columns; // Ceiling division - + let rows = total_codewords.div_ceil(columns); + // PDF417 must have 3-90 rows - rows.max(3).min(90) + rows.clamp(3, 90) } #[cfg(test)] @@ -170,14 +172,29 @@ mod tests { let result1 = calculate_rows(10, 6, 2); let result2 = calculate_rows(100, 6, 2); let result3 = calculate_rows(1000, 6, 2); - + // PDF417 should have 3-90 rows - assert!(result1 >= 3 && result1 <= 90, "Rows should be 3-90, got {}", result1); - assert!(result2 >= 3 && result2 <= 90, "Rows should be 3-90, got {}", result2); - assert!(result3 >= 3 && result3 <= 90, "Rows should be 3-90, got {}", result3); - + assert!( + (3..=90).contains(&result1), + "Rows should be 3-90, got {}", + result1 + ); + assert!( + (3..=90).contains(&result2), + "Rows should be 3-90, got {}", + result2 + ); + assert!( + (3..=90).contains(&result3), + "Rows should be 3-90, got {}", + result3 + ); + // Larger data should need more rows assert!(result2 > result1, "More data should need more rows"); - assert!(result3 >= result2, "Much more data should need at least as many rows"); + assert!( + result3 >= result2, + "Much more data should need at least as many rows" + ); } } diff --git a/src/lib.rs b/src/lib.rs index e05e8bf..90b3b85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,21 +78,23 @@ pub fn generate( BarcodeType::EAN13 => generators::ean13::generate_ean13(data)?, BarcodeType::UPCA => generators::upc::generate_upc_a(data)?, BarcodeType::Code128 => generators::code128::generate_code128(data)?, - + // Phase 2: Advanced 2D codes BarcodeType::DataMatrix => generators::datamatrix::generate_datamatrix(data)?, BarcodeType::PDF417 => generators::pdf417::generate_pdf417(data)?, BarcodeType::Aztec => generators::aztec::generate_aztec(data)?, - + // Phase 3: Legacy formats (not yet implemented) BarcodeType::Code39 | BarcodeType::ITF14 | BarcodeType::Codabar => { - return Err(anyhow::anyhow!("Barcode type {} not yet implemented - coming in Phase 3", + return Err(anyhow::anyhow!( + "Barcode type {} not yet implemented - coming in Phase 3", match barcode_type { BarcodeType::Code39 => "Code39", - BarcodeType::ITF14 => "ITF-14", + BarcodeType::ITF14 => "ITF-14", BarcodeType::Codabar => "Codabar", - _ => unreachable!() - })) + _ => unreachable!(), + } + )) } }; diff --git a/src/python.rs b/src/python.rs index 84a52e0..230ee1e 100644 --- a/src/python.rs +++ b/src/python.rs @@ -173,7 +173,7 @@ fn generate( "EAN13" => BarcodeType::EAN13, "UPCA" => BarcodeType::UPCA, "Code128" => BarcodeType::Code128, - + // Phase 2: Advanced 2D codes "DataMatrix" => BarcodeType::DataMatrix, "PDF417" => BarcodeType::PDF417, @@ -235,7 +235,7 @@ fn generate_to_file(barcode_type: &str, data: &str, output_path: &str) -> PyResu "EAN13" => BarcodeType::EAN13, "UPCA" => BarcodeType::UPCA, "Code128" => BarcodeType::Code128, - + // Phase 2: Advanced 2D codes "DataMatrix" => BarcodeType::DataMatrix, "PDF417" => BarcodeType::PDF417, @@ -276,7 +276,7 @@ fn quickcodes(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add("EAN13", "EAN13")?; m.add("UPC_A", "UPCA")?; m.add("CODE128", "Code128")?; - + // Phase 2: Advanced 2D codes m.add("DATA_MATRIX", "DataMatrix")?; m.add("PDF417", "PDF417")?;