Repository: astral-sh/uv
File: crates/uv-auth/src/pyx.rs (Rust)

Code before:
    /// For OAuth tokens, uses a fixed "tokens.lock" file.
    /// For API key tokens, uses a file based on the API key digest.
    fn lock_path(&self, tokens: &PyxTokens) -> PathBuf {
        match tokens {
            PyxTokens::OAuth(_) => self.subdirectory.join("tokens.lock"),
            PyxTokens::ApiKey(PyxApiKeyTokens { api_key, .. }) => {
                let digest = uv_cache_key::cache_digest(api_key);
                self.subdirectory.join(format!("{digest}.lock"))
            }
        }
    }

    /// Read the last refresh timestamp from the lock file.
    async fn read_last_refresh(&self, lock_path: &Path) -> Option<u64> {
        let data = fs_err::tokio::read_to_string(lock_path).await.ok()?;
        data.trim().parse().ok()
    }

    /// Write the current timestamp to the lock file.
    async fn write_last_refresh(&self, lock_path: &Path) -> Result<(), io::Error> {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .expect("system time before Unix epoch")
            .as_secs();
        fs_err::tokio::write(lock_path, now.to_string()).await
    }

    /// Bootstrap the tokens from the store.
    async fn bootstrap(
        &self,
        client: &ClientWithMiddleware,
    ) -> Result<Option<PyxTokens>, TokenStoreError> {
        #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
        struct Payload {
            access_token: AccessToken,
        }

        // Retrieve the API key from the environment variable, if set.
        let Some(api_key) = read_pyx_api_key() else {
            return Ok(None);
        };

        debug!("Bootstrapping access token from an API key");

        // Parse the API URL.
        let mut url = self.api.clone();
        url.set_path("auth/cli/access-token");

        let mut request = reqwest::Request::new(reqwest::Method::POST, Url::from(url));
        request.headers_mut().insert(
            "Authorization",

Review comment (suggestion):
I would version the contents of this lockfile, just in case we need to change its contents in future releases. It could be as simple as the first 2 bytes containing a version marker, followed by content

Code after:
                let digest = uv_cache_key::cache_digest(api_key);
                self.subdirectory.join(format!("{digest}.lock"))
            }
        }
    }

    /// Bootstrap the tokens from the store.
    async fn bootstrap(
        &self,
        client: &ClientWithMiddleware,
    ) -> Result<Option<PyxTokens>, TokenStoreError> {
        #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
        struct Payload {
            access_token: AccessToken,
        }

        // Retrieve the API key from the environment variable, if set.
        let Some(api_key) = read_pyx_api_key() else {
            return Ok(None);
        };

        debug!("Bootstrapping access token from an API key");

        // Parse the API URL.
        let mut url = self.api.clone();
        url.set_path("auth/cli/access-token");

        let mut request = reqwest::Request::new(reqwest::Method::POST, Url::from(url));
        request.headers_mut().insert(
            "Authorization",
            reqwest::header::HeaderValue::from_str(&format!("Bearer {api_key}"))?,
        );

        let response = client.execute(request).await?;
        let Payload { access_token } = response.error_for_status()?.json::<Payload>().await?;
        let tokens = PyxTokens::ApiKey(PyxApiKeyTokens {
            access_token,
            api_key,
        });

        // Write the tokens to disk.
        self.write(&tokens).await?;

        Ok(Some(tokens))
    }

    /// Refresh the tokens in the store, if they are expired.
    ///
    /// In theory, we should _also_ refresh if we hit a 401; but for now, we only refresh ahead of
    /// time.
    async fn refresh(