1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
//! # GitHub Bot SDK
//!
//! A comprehensive Rust SDK for building GitHub Apps and bots with strong type safety,
//! built-in security, and production-ready patterns.
//!
//! ## Features
//!
//! - **GitHub App Authentication** - RS256 JWT signing and automated installation token management
//! - **🌐 API Client** - Type-safe GitHub REST API operations with automatic rate limiting
//! - **Webhook Security** - HMAC-SHA256 signature validation with constant-time comparison
//! - **Event Processing** - Structured webhook event parsing and routing
//! - **Production Ready** - Exponential backoff, retry logic, and comprehensive error handling
//! - **Rust First** - Zero-cost abstractions leveraging Rust's type system for correctness
//!
//! ## Quick Start
//!
//! Add to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! github-bot-sdk = "0.1.0"
//! tokio = { version = "1.0", features = ["full"] }
//! ```
//!
//! ## Core Concepts
//!
//! ### Authentication
//!
//! GitHub Apps use a two-tier authentication model:
//!
//! 1. **App-level JWT** - Short-lived tokens (max 10 minutes) for app-level operations
//! 2. **Installation Tokens** - Scoped tokens for operations on behalf of installations
//!
//! This SDK handles both automatically through the [`AuthenticationProvider`] trait.
//!
//! ### API Client
//!
//! The [`GitHubClient`] provides typed access to GitHub's REST API with:
//!
//! - Automatic token injection and refresh
//! - Built-in rate limit detection and handling
//! - Exponential backoff retry for transient failures
//! - Pagination support for list operations
//!
//! ### Webhook Processing
//!
//! Validate and process GitHub webhooks securely:
//!
//! - HMAC-SHA256 signature verification via [`SignatureValidator`]
//! - Structured event parsing with [`events`] module
//! - Type-safe event routing and handling
//!
//! ## Usage Examples
//!
//! ### Basic GitHub Client Usage
//!
//! ```rust,no_run
//! use github_bot_sdk::{
//! auth::{GitHubAppId, InstallationId, AuthenticationProvider},
//! client::{GitHubClient, ClientConfig},
//! error::ApiError,
//! };
//!
//! # async fn example(auth_provider: impl AuthenticationProvider + 'static) -> Result<(), ApiError> {
//! // Build GitHub client with authentication
//! let client = GitHubClient::builder(auth_provider)
//! .config(ClientConfig::default()
//! .with_user_agent("my-bot/1.0")
//! .with_timeout(std::time::Duration::from_secs(30)))
//! .build()?;
//!
//! // Get app information
//! let app = client.get_app().await?;
//! println!("Authenticated as: {}", app.name);
//!
//! // Get installation information
//! let installation_id = InstallationId::new(12345);
//! let installation = client.get_installation(installation_id).await?;
//! println!("Installation ID: {}", installation.id.as_u64());
//! # Ok(())
//! # }
//! ```
//!
//! ### Repository Operations
//!
//! ```rust,no_run
//! # use github_bot_sdk::client::GitHubClient;
//! # use github_bot_sdk::auth::InstallationId;
//! # async fn example(client: &GitHubClient) -> Result<(), Box<dyn std::error::Error>> {
//! let installation_id = InstallationId::new(12345);
//! let installation = client.get_installation(installation_id).await?;
//!
//! // Get installation details
//! println!("Installation ID: {}", installation.id.as_u64());
//! println!("Account: {}", installation.account.login);
//! # Ok(())
//! # }
//! ```
//!
//! ### Issue and Pull Request Operations
//!
//! ```rust,no_run
//! # use github_bot_sdk::client::GitHubClient;
//! # use github_bot_sdk::auth::InstallationId;
//! # async fn example(client: &GitHubClient) -> Result<(), Box<dyn std::error::Error>> {
//! let installation_id = InstallationId::new(12345);
//!
//! // Get installation to work with issues and pull requests
//! let installation = client.get_installation(installation_id).await?;
//! println!("Working with installation: {}", installation.id.as_u64());
//!
//! // See client module documentation for repository, issue, and PR operations
//! # Ok(())
//! # }
//! ```
//!
//! ### Webhook Signature Validation
//!
//! ```rust,no_run
//! use github_bot_sdk::{
//! webhook::SignatureValidator,
//! auth::SecretProvider,
//! error::ValidationError,
//! };
//! use std::sync::Arc;
//!
//! # async fn example(secret_provider: Arc<dyn SecretProvider>) -> Result<(), ValidationError> {
//! let validator = SignatureValidator::new(secret_provider);
//!
//! // Validate incoming webhook
//! let payload = b"{\"action\":\"opened\",\"issue\":{...}}";
//! let signature = "sha256=5c4a8d..."; // From X-Hub-Signature-256 header
//!
//! if validator.validate(payload, signature).await? {
//! println!("✓ Valid webhook - processing event");
//! // Parse and process the event
//! } else {
//! println!("✗ Invalid signature - rejecting webhook");
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ### Working with Tokens
//!
//! ```rust
//! use github_bot_sdk::auth::{JsonWebToken, GitHubAppId};
//! use chrono::{Utc, Duration};
//!
//! let app_id = GitHubAppId::new(123456);
//! let expires_at = Utc::now() + Duration::minutes(10);
//! let jwt = JsonWebToken::new("eyJ0...".to_string(), app_id, expires_at);
//!
//! // Check expiration
//! if jwt.is_expired() {
//! println!("Token has expired");
//! }
//!
//! // Check if token expires soon (within 5 minutes)
//! if jwt.expires_soon(Duration::minutes(5)) {
//! println!("Token expires soon - should refresh");
//! }
//! ```
//!
//! ## Module Organization
//!
//! - [`auth`] - Authentication types, traits, and token management
//! - [`client`] - GitHub API client and operation implementations
//! - [`error`] - Error types for all operations
//! - [`events`] - Webhook event parsing and processing
//! - [`webhook`] - Webhook signature validation and security
//!
//! ## Architecture
//!
//! This SDK follows hexagonal architecture principles:
//!
//! - **Core Domain** - Authentication, events, and API operations (in this crate)
//! - **Abstraction Layer** - Traits for external dependencies ([`SecretProvider`], [`JwtSigner`], etc.)
//! - **Infrastructure** - Your implementations for secret management, key storage, etc.
//!
//! This design ensures:
//! - Testability through dependency injection
//! - Flexibility to integrate with your infrastructure
//! - Type safety at compile time
//! - Clear separation of concerns
//!
//! ## Security
//!
//! Security is built into the SDK's design:
//!
//! - **No Token Logging** - Sensitive types implement custom `Debug` that redacts secrets
//! - **Memory Safety** - Token types zero memory on drop
//! - **Constant-Time Comparison** - Webhook signatures use timing-attack resistant comparison
//! - **HTTPS Only** - All GitHub API communication uses TLS
//! - **Type Safety** - Branded types prevent mixing up different ID types
//!
//! ## Error Handling
//!
//! All operations return `Result<T, E>` with rich error types:
//!
//! - [`ApiError`] - GitHub API errors, rate limits, network failures
//! - [`AuthError`] - Authentication and token errors
//! - [`ValidationError`] - Input validation and webhook signature errors
//! - [`EventError`] - Event parsing and processing errors
//!
//! Errors include context for debugging and implement retry classification
//! to distinguish transient failures from permanent errors.
//!
//! ## Rate Limiting
//!
//! The SDK automatically handles GitHub's rate limits:
//!
//! - Detects rate limit headers in responses
//! - Automatically backs off when approaching limits
//! - Respects `Retry-After` headers on 429 responses
//! - Configurable safety margin to avoid hitting limits
//!
//! ## Testing
//!
//! The SDK is designed for testability:
//!
//! - Mock implementations for all traits
//! - [`wiremock`](https://docs.rs/wiremock) integration for HTTP mocking
//! - Comprehensive test coverage
//! - Doc tests for all examples
//!
//! ## Specifications
//!
//! For detailed architectural specifications, see [`docs/specs/`](https://github.com/pvandervelde/github-bot-sdk/tree/master/docs/specs).
//!
//! ## Examples
//!
//! See the [repository examples](https://github.com/pvandervelde/github-bot-sdk/tree/master/examples)
//! for complete, runnable examples demonstrating common use cases.
// Public modules
// Re-export commonly used types at crate root for convenience
pub use ;
pub use ;
pub use ;
pub use SignatureValidator;