auths_sdk/ports/git.rs
1//! Git log provider port for audit and compliance workflows.
2//!
3//! Defines the trait boundary for reading commit history.
4//! Production adapters (e.g. git2-based) live in infra crates.
5
6/// A single commit record from the repository history.
7///
8/// Args:
9/// * `hash`: The abbreviated commit hash.
10/// * `author_name`: The commit author's name.
11/// * `author_email`: The commit author's email.
12/// * `timestamp`: ISO-8601 formatted commit timestamp.
13/// * `message`: First line of the commit message.
14/// * `signature_status`: Classification of the commit's signature.
15///
16/// Usage:
17/// ```ignore
18/// let record = CommitRecord {
19/// hash: "abc1234".to_string(),
20/// author_name: "Alice".to_string(),
21/// author_email: "alice@example.com".to_string(),
22/// timestamp: "2024-01-15T10:00:00Z".to_string(),
23/// message: "initial commit".to_string(),
24/// signature_status: SignatureStatus::Unsigned,
25/// };
26/// ```
27#[derive(Debug, Clone)]
28pub struct CommitRecord {
29 /// The abbreviated commit hash.
30 pub hash: String,
31 /// The commit author's name.
32 pub author_name: String,
33 /// The commit author's email.
34 pub author_email: String,
35 /// ISO-8601 formatted commit timestamp.
36 pub timestamp: String,
37 /// First line of the commit message.
38 pub message: String,
39 /// Classification of the commit's signature.
40 pub signature_status: SignatureStatus,
41}
42
43/// Classification of a commit's cryptographic signature.
44///
45/// Usage:
46/// ```ignore
47/// match status {
48/// SignatureStatus::AuthsSigned { signer_did } => println!("Signed by {signer_did}"),
49/// SignatureStatus::SshSigned => println!("SSH signed"),
50/// SignatureStatus::GpgSigned { verified } => println!("GPG signed, verified={verified}"),
51/// SignatureStatus::Unsigned => println!("No signature"),
52/// SignatureStatus::InvalidSignature { reason } => println!("Bad sig: {reason}"),
53/// }
54/// ```
55#[derive(Debug, Clone)]
56pub enum SignatureStatus {
57 /// Signed using the auths workflow.
58 AuthsSigned {
59 /// The DID of the signer.
60 signer_did: String,
61 },
62 /// Signed using SSH.
63 SshSigned,
64 /// Signed using GPG.
65 GpgSigned {
66 /// Whether the GPG signature was verified.
67 verified: bool,
68 },
69 /// No signature present.
70 Unsigned,
71 /// A signature was present but invalid.
72 InvalidSignature {
73 /// The reason the signature is invalid.
74 reason: String,
75 },
76}
77
78/// Errors from git log provider operations.
79#[derive(Debug, thiserror::Error)]
80pub enum GitProviderError {
81 /// Failed to open the git repository.
82 #[error("failed to open repository: {0}")]
83 Open(String),
84 /// Failed to walk the commit history.
85 #[error("failed to walk commits: {0}")]
86 Walk(String),
87 /// An object ID could not be parsed.
88 #[error("invalid oid: {0}")]
89 InvalidOid(String),
90 /// The requested commit was not found.
91 #[error("commit not found: {0}")]
92 NotFound(String),
93 /// The repository lock was poisoned by a panicking thread.
94 #[error("repository lock poisoned")]
95 LockPoisoned,
96}
97
98/// Port for reading commit history from a Git repository.
99///
100/// Usage:
101/// ```ignore
102/// let commits: Vec<CommitRecord> = provider
103/// .walk_commits(None, Some(100))?
104/// .collect::<Result<Vec<_>, _>>()?;
105/// ```
106pub trait GitLogProvider: Send + Sync {
107 /// Walk commit history, optionally constrained by a range spec and limit.
108 ///
109 /// Args:
110 /// * `range`: Optional git revision range (e.g. "HEAD~10..HEAD").
111 /// * `limit`: Optional maximum number of commits to return.
112 fn walk_commits(
113 &self,
114 range: Option<&str>,
115 limit: Option<usize>,
116 ) -> Result<Vec<CommitRecord>, GitProviderError>;
117}