Skip to content

Commit 4b6070b

Browse files
authored
feat(cli): add dump-client-creds to print an account's stored BYO OAuth client (#166)
Mirrors the existing dump-refresh-token debug command: prints the keychain-stored client_id + client_secret (one per line; empty second line for a PKCE client) for an account, keyed the same way the GUI stores them (account UUID). Why: a refresh token is bound to the OAuth client that minted it; debugging a refresh failure or doing Drive-side forensics requires the SAME client pair the app uses. Used today to confirm a real incident: stored drive_file_ids returning hard 404s from the Drive API. No behavior change to any existing command. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01JLB3E2Jm7knNJd37fVpH8X
1 parent 4896336 commit 4b6070b

1 file changed

Lines changed: 39 additions & 1 deletion

File tree

crates/driven-cli/src/main.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ use clap::{Parser, Subcommand};
3030
mod inspect;
3131

3232
use driven_drive::google::oauth::{run_pkce_loopback_flow, OAuthProgress};
33-
use driven_drive::google::token_store::{KeyringTokenStore, RefreshingTokenSource};
33+
use driven_drive::google::token_store::{
34+
ClientCredsStore, KeyringTokenStore, RefreshingTokenSource,
35+
};
3436
use driven_drive::google::{md5_hex, parse_installed_client_config, GoogleDriveStore, UploadBytes};
3537
use driven_drive::remote_store::{RemoteStore, UploadBody};
3638
use driven_drive::{CustomCaConfig, ProxyConfig};
@@ -58,6 +60,10 @@ enum Command {
5860
/// Print the stored refresh token for the authenticated account so it can
5961
/// be exported as `DRIVEN_E2E_REFRESH_TOKEN` (ROADMAP M4).
6062
DumpRefreshToken(DumpRefreshTokenArgs),
63+
/// Print the stored BYO OAuth client id + secret for an account (the pair
64+
/// that minted its refresh token), for debugging refresh failures. The
65+
/// GUI app stores these under the account's UUID.
66+
DumpClientCreds(DumpClientCredsArgs),
6167
/// Run one sync cycle of a local folder to a real Drive destination
6268
/// folder (ROADMAP M4 acceptance).
6369
Sync(SyncArgs),
@@ -99,6 +105,16 @@ struct DumpRefreshTokenArgs {
99105
account: String,
100106
}
101107

108+
/// Arguments for `driven-cli dump-client-creds`.
109+
#[derive(Debug, clap::Args)]
110+
struct DumpClientCredsArgs {
111+
/// The account whose stored BYO client creds to print (keychain lookup
112+
/// key; the GUI app keys by account UUID, `driven-cli auth` by the
113+
/// account string given at auth time).
114+
#[arg(long)]
115+
account: String,
116+
}
117+
102118
/// Arguments for `driven-cli sync`.
103119
#[derive(Debug, clap::Args)]
104120
struct SyncArgs {
@@ -140,6 +156,7 @@ async fn main() -> anyhow::Result<()> {
140156
match cli.command {
141157
Command::Auth(args) => run_auth(args).await,
142158
Command::DumpRefreshToken(args) => run_dump_refresh_token(args).await,
159+
Command::DumpClientCreds(args) => run_dump_client_creds(args).await,
143160
Command::Sync(args) => run_sync(args).await,
144161
Command::Status(args) => inspect::run_status(args).await,
145162
Command::History(args) => inspect::run_history(args).await,
@@ -311,6 +328,27 @@ async fn run_dump_refresh_token(args: DumpRefreshTokenArgs) -> anyhow::Result<()
311328
}
312329
}
313330

331+
/// Handler for `driven-cli dump-client-creds`.
332+
///
333+
/// Mirrors [`run_dump_refresh_token`]: prints `client_id` then `client_secret`
334+
/// (one per line; the secret line is empty for a PKCE client) so a debugging
335+
/// session can refresh the account's token against the SAME client that minted
336+
/// it - a refresh against any other client fails with `invalid_client`.
337+
async fn run_dump_client_creds(args: DumpClientCredsArgs) -> anyhow::Result<()> {
338+
let store = ClientCredsStore::new(args.account.clone());
339+
match store.load()? {
340+
Some(creds) => {
341+
println!("{}", creds.client_id);
342+
println!("{}", creds.client_secret);
343+
Ok(())
344+
}
345+
None => Err(anyhow::anyhow!(
346+
"no BYO client creds stored for account '{}'",
347+
args.account
348+
)),
349+
}
350+
}
351+
314352
/// Handler for `driven-cli sync` (ROADMAP M4 acceptance).
315353
///
316354
/// Builds a [`GoogleDriveStore`] from the stored refresh token and uploads

0 commit comments

Comments
 (0)