Contributing Guide
Thank you for your interest in contributing to FIDO Bridge! This document provides guidelines for contributing to the project.
Code of Conduct
Be respectful and constructive in all interactions. We're building this together!
Expected Behavior:
- Be welcoming to newcomers
- Provide constructive feedback
- Focus on what's best for the community
- Show empathy toward others
Unacceptable Behavior:
- Harassment or discriminatory language
- Personal attacks or trolling
- Publishing others' private information
- Any conduct that would be inappropriate in a professional setting
How to Contribute
Reporting Bugs
Before submitting a bug report:
- Check the troubleshooting guide
- Search existing GitHub issues
- Test with latest version from
mainbranch
When submitting a bug report, include:
- Title: Clear, descriptive summary
- Description: What happened vs. what you expected
- Steps to reproduce: Minimal steps to trigger the bug
- Environment:
- OS and version
- Rust version (
rustc --version) - Flutter version (
flutter --version) - YubiKey model
- Logs: Debug logs showing the error (sanitize secrets!)
- Screenshots: If relevant (UI bugs)
Template:
## Bug Description
[Clear description of the bug]
## Steps to Reproduce
1. Start Linux client with `sudo ./target/release/client`
2. Pair Android device
3. Attempt WebAuthn authentication on https://webauthn.io
4. Error occurs: [describe error]
## Expected Behavior
[What should have happened]
## Actual Behavior
[What actually happened]
## Environment
- OS: Ubuntu 24.04 LTS
- Rust: 1.75.0
- Flutter: 3.16.0
- YubiKey: YubiKey 5 NFC (firmware 5.4.3)
## Logs
[Paste relevant logs here]
## Screenshots
[If applicable]
Suggesting Features
Before suggesting a feature:
- Search existing issues to avoid duplicates
- Consider if it fits FIDO Bridge's scope
- Think about implementation complexity
When suggesting a feature, describe:
- Use case: Why is this needed?
- Proposed solution: How would it work?
- Alternatives: Other ways to achieve the same goal?
- Complexity: Simple enhancement or major change?
Label: Use enhancement label on GitHub
Contributing Code
1. Find an Issue
- Browse good first issues
- Or create an issue for what you want to work on
- Comment on the issue to claim it (avoids duplicate work)
2. Fork and Clone
# Fork on GitHub, then:
git clone https://github.com/YOUR_USERNAME/fido-bridge.git
cd fido-bridge
git remote add upstream https://github.com/0xC9C3/fido-bridge.git
3. Create a Branch
# Feature branch
git checkout -b feature/my-feature-name
# Bugfix branch
git checkout -b fix/issue-123-bug-description
Branch naming:
feature/descriptionfor new featuresfix/issue-number-descriptionfor bug fixesdocs/descriptionfor documentation changesrefactor/descriptionfor code refactoring
4. Make Changes
Follow the code style guidelines below.
5. Write Tests
- Add tests for new functionality
- Ensure existing tests pass:
cargo test && cd app && flutter test - Aim for 80%+ test coverage on new code
6. Update Documentation
- Update relevant
.mdfiles in/docs/docs/ - Add inline code comments (WHY, not WHAT)
- Update
CHANGELOG.md(if applicable)
7. Commit Changes
We use conventional commits for all commits. The repository has tooling to help you create properly formatted commits automatically.
Using the interactive commit tool (recommended):
# Use commitizen for an interactive prompt
npm run commit
This will guide you through creating a properly formatted commit message.
Manual commits:
# Format: type(scope): description
git commit -m "feat(client): add session cache for ClientPIN"
git commit -m "fix(android): resolve NFC timeout on Pixel devices"
git commit -m "docs(guides): add troubleshooting for pairing timeout"
Note: Commit messages are automatically validated using commitlint via a git hook.
Commit types:
feat: New feature (triggers minor version bump)fix: Bug fix (triggers patch version bump)perf: Performance improvement (triggers patch version bump)refactor: Code refactoring (triggers patch version bump)build: Build system changes (triggers patch version bump)revert: Revert previous change (triggers patch version bump)docs: Documentation changes (no release)style: Code style changes (no release)test: Adding or updating tests (no release)ci: CI/CD changes (no release)chore: Maintenance tasks (no release)
Commit message guidelines:
- Use present tense ("add feature" not "added feature")
- Keep first line under 100 characters
- Provide detailed description in body (if needed)
- Reference issues:
Fixes #123orCloses #456 - Add
BREAKING CHANGE:in footer for breaking changes (triggers major version bump)
8. Push and Create Pull Request
git push origin feature/my-feature-name
On GitHub:
- Click "Create Pull Request"
- Fill out the PR template
- Link related issues
- Request review from maintainers
Pull Request Guidelines
PR Title: Follow conventional commits format
feat(client): add support for biometric authentication
fix(android): resolve NFC communication timeout
docs(architecture): add PRF extension documentation
PR Description should include:
- What: What changes does this PR make?
- Why: Why are these changes needed?
- How: How were the changes implemented?
- Testing: How was this tested?
- Related Issues:
Fixes #123orRelates to #456 - Screenshots: If UI changes
Template:
## Summary
[Brief description of changes]
## Changes
- [Change 1]
- [Change 2]
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests pass
- [ ] Manual testing performed
- [ ] E2E test scenario: [describe]
## Checklist
- [ ] Code follows style guidelines
- [ ] Tests added for new functionality
- [ ] Documentation updated
- [ ] Commit messages follow conventional commits
- [ ] No breaking changes (or clearly documented)
## Related Issues
Fixes #123
Relates to #456
Review Process:
- Automated CI checks must pass (tests, linting)
- At least one maintainer approval required
- Address feedback in new commits (don't force-push during review)
- Maintainer will squash-merge when approved
Code Style Guidelines
Rust Code Style
Use rustfmt:
cargo fmt --all
Use clippy:
cargo clippy --all-targets --all-features -- -D warnings
Conventions:
- Function names:
snake_case - Type names:
PascalCase - Constants:
SCREAMING_SNAKE_CASE - Max line length: 100 characters (soft limit)
- Imports: Group by
std,external crates,internal modules
Comment Style:
// WHY: Explain *why* code exists, not *what* it does
// Good:
// Session cache reduces NFC taps during multi-step ClientPIN flows
let session_cache_ttl = Duration::from_secs(30);
// Bad:
// Set timeout to 30 seconds
let session_cache_ttl = Duration::from_secs(30);
Error Handling:
// Use Result types, not panic!()
pub fn parse_ctap_response(data: &[u8]) -> Result<CtapResponse, Error> {
if data.len() < 2 {
return Err(Error::InvalidResponse("Too short".to_string()));
}
// ...
}
// Document error conditions
/// Parse CTAP2 response from raw bytes
///
/// # Errors
/// Returns `Error::InvalidResponse` if data is too short or malformed
pub fn parse_ctap_response(data: &[u8]) -> Result<CtapResponse, Error> {
// ...
}
Async Style:
// Prefer async/await over manual futures
async fn send_message(&self, msg: Message) -> Result<(), Error> {
let response = self.client.post("/api/messages")
.json(&msg)
.send()
.await?;
response.error_for_status()?;
Ok(())
}
Dart/Flutter Code Style
Use dart format:
cd app
dart format lib test
Use dart analyze:
dart analyze
Conventions:
- Class names:
PascalCase - Function/variable names:
camelCase - Private members:
_leadingUnderscore - Constants:
lowerCamelCase(unless const class)
Widget Structure:
class MyWidget extends StatelessWidget {
const MyWidget({
super.key,
required this.title,
this.subtitle,
});
final String title;
final String? subtitle;
Widget build(BuildContext context) {
return Column(
children: [
Text(title),
if (subtitle != null) Text(subtitle!),
],
);
}
}
State Management (Riverpod):
// Use Riverpod providers for state
final pairedDevicesProvider = StateNotifierProvider<PairedDevicesNotifier, List<Device>>((ref) {
return PairedDevicesNotifier();
});
// Consume in widgets
class DeviceList extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final devices = ref.watch(pairedDevicesProvider);
return ListView(children: devices.map((d) => DeviceTile(d)).toList());
}
}
Kotlin Code Style
Use Android Studio formatter (Ctrl+Alt+L)
Conventions:
- Follow Kotlin coding conventions
- Max line length: 120 characters
- Use
valovervarwhen possible
class NfcHandler(private val context: Context) {
fun handleTag(tag: Tag): ByteArray {
val isoDep = IsoDep.get(tag)
isoDep.connect()
try {
return transceiveApdu(isoDep, SELECT_FIDO_APPLET)
} finally {
isoDep.close()
}
}
private fun transceiveApdu(isoDep: IsoDep, command: ByteArray): ByteArray {
// Implementation
}
}
Documentation Guidelines
Inline Documentation
Rust:
/// Parse a CTAP2 GetInfo response from CBOR-encoded bytes.
///
/// # Arguments
/// * `data` - Raw CBOR response from authenticator
///
/// # Returns
/// Parsed `GetInfoResponse` containing authenticator capabilities
///
/// # Errors
/// Returns `Error::InvalidResponse` if CBOR parsing fails or required fields are missing
///
/// # Example
/// ```
/// let response_bytes = vec![0xa6, 0x01, 0x58, ...];
/// let info = parse_getinfo_response(&response_bytes)?;
/// assert!(info.versions.contains(&"FIDO_2_0".to_string()));
/// ```
pub fn parse_getinfo_response(data: &[u8]) -> Result<GetInfoResponse, Error> {
// Implementation
}
Dart:
/// Sends an APDU command to the YubiKey via NFC.
///
/// The command is transmitted using ISO 14443A protocol. Throws a
/// [NfcException] if communication fails or timeout occurs.
///
/// Example:
/// ```dart
/// final response = await sendApduCommand([0x00, 0xA4, 0x04, 0x00]);
/// if (response.last == 0x90 && response[response.length - 2] == 0x00) {
/// print('Command successful');
/// }
/// ```
Future<Uint8List> sendApduCommand(List<int> command) async {
// Implementation
}
Markdown Documentation
- Use ATX-style headings (
#not===) - One sentence per line (easier diffs)
- Code blocks with language tags:
```rust - Use relative links for internal docs:
[link](../other-doc.md)
Testing Requirements
For New Features
- Unit tests: Cover new functions/methods
- Integration tests: Cover interactions with existing code
- Documentation: Update relevant docs
- Changelog: Add entry to
CHANGELOG.md
For Bug Fixes
- Regression test: Add test that would have caught the bug
- Verify fix: Ensure test passes with fix, fails without
- Update docs: If bug was due to unclear documentation
Test Coverage Expectations
- Cryptographic code: 100% coverage (security-critical)
- Protocol parsing: 90%+ coverage
- UI code: 50%+ coverage (focus on logic, not layout)
- Overall: 80%+ coverage
Run coverage:
# Rust
cargo tarpaulin --out Html
# Flutter
cd app && flutter test --coverage
Security Contributions
Security Code Reviews
All PRs touching cryptographic code or authentication flows will receive extra scrutiny:
- Multiple maintainer reviews required
- Security-focused testing required
- Potential external security audit
Security-sensitive areas:
/crates/transport/src/pairing/crypto.rs(SPAKE2, cryptographic primitives)/crates/transport/src/secure_channel.rs(X25519 ECDH, AES-GCM encryption)/crates/client/src/storage.rs(Paired device credential storage)- Any PIN or secret handling code
Project Workflow
Branching Strategy
main: Stable, production-ready codedevelop: Integration branch for features (optional, if used)- Feature branches: Short-lived branches for individual features/fixes
Release Process
- Version bump: Update version in
Cargo.tomlandpubspec.yaml - Changelog: Update
CHANGELOG.mdwith release notes - Tag: Create git tag
vX.Y.Z - Build: Create release builds for all platforms
- Publish: GitHub release with binaries and APK
Versioning: We follow Semantic Versioning:
- MAJOR: Breaking changes
- MINOR: New features (backward-compatible)
- PATCH: Bug fixes (backward-compatible)
Continuous Integration
All PRs must pass CI checks:
- Rust tests:
cargo test --all-features - Rust linting:
cargo clippy -- -D warnings - Rust formatting:
cargo fmt --check - Flutter tests:
flutter test - Flutter analysis:
flutter analyze - Build check: Ensure all components build successfully
CI runs on GitHub Actions (see .github/workflows/).
Communication
Preferred Channels
- GitHub Issues: Bug reports, feature requests
- GitHub Discussions: General questions, ideas
- Pull Requests: Code contributions
Response Times
We aim to:
- Acknowledge issues within 7 days
- Review PRs within 14 days (sooner for small/urgent changes)
- Security issues acknowledged within 48 hours
Recognition
Contributors will be:
- Listed in
CONTRIBUTORS.md - Credited in release notes
- Thanked in project documentation
Significant contributions may receive:
- Maintainer status
- Invitation to project discussions
- Recognition in project README
Getting Help
New to contributing?
- Check out good first issues
- Ask questions in GitHub Discussions
- Read Building from Source and Testing guides
Stuck on something?
- Comment on the relevant issue or PR
- Ask in GitHub Discussions
- Reach out to maintainers
We're here to help! Everyone was a beginner once.
License
By contributing to FIDO Bridge, you agree that your contributions will be licensed under the project's dual MIT OR Apache-2.0 license.
See LICENSE-MIT and LICENSE-APACHE for details.
Thank You!
Thank you for contributing to FIDO Bridge and helping make secure authentication accessible to everyone!