Metadata-Version: 2.4
Name: hestia-keyring
Version: 1.0.2
Summary: Keyring backend for HES Azure Artifacts — enables uv sync without PATs
License: MIT
Requires-Python: >=3.13
Requires-Dist: azure-identity>=1.19
Requires-Dist: keyring>=24.0
Description-Content-Type: text/markdown

# hestia-keyring

A [keyring](https://pypi.org/project/keyring/) backend that authenticates `uv sync` against
the HES Azure Artifacts feed using your active `az` CLI session — no Personal Access Tokens
required.

## Install once per machine

```bash
uv tool install keyring --with hestia-keyring
```

## What it does

When `uv` calls `keyring get https://pkgs.dev.azure.com/... VssSessionToken`, this backend
runs `az account get-access-token --resource https://app.vssps.visualstudio.com` and returns
the resulting bearer token. Your `az login` session is the only credential you need.

## Requirements

- Python 3.13+
- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) installed and
  signed in (`az login`)

## Why this package and not the official uv approach?

The [uv Azure docs](https://docs.astral.sh/uv/guides/integration/azure/) suggest two alternatives:

**Option A — `artifacts-keyring`:**
```bash
uv tool install keyring --with artifacts-keyring
export UV_KEYRING_PROVIDER=subprocess
export UV_INDEX_PRIVATE_REGISTRY_USERNAME=VssSessionToken
```

`artifacts-keyring` is a thin wrapper around the **Azure Artifacts Credential Provider** — a
.NET binary (`CredentialProvider.Microsoft.exe`) that Microsoft ships separately. When
`artifacts-keyring` is called, it shells out to that binary to acquire a token. On company
hardware the binary is not installed (it requires the .NET SDK or the Azure DevOps agent
toolchain), so `artifacts-keyring` silently returns nothing and every `uv sync` ends with a
401.

**Option B — access token via env var:**
```bash
export UV_INDEX_HES_INTERNAL_USERNAME=VssSessionToken
export UV_INDEX_HES_INTERNAL_PASSWORD=$(az account get-access-token \
  --resource https://app.vssps.visualstudio.com --query accessToken --output tsv)
```

This works, but the token expires every hour and must be re-exported manually each session.
It also can't be wired into `pyproject.toml` — each developer must set the env var themselves.

**Why `hestia-keyring`:**

- **Pure Python** — uses `azure-identity.DefaultAzureCredential` with no .NET runtime or
  binary dependencies
- **Transparent** — once installed, `uv sync` just works; no env vars to set per session
- **Token caching** — the access token is reused for 5 minutes so repeated `uv sync` calls
  are fast
- **One `az login`** — authenticates using the same browser session you already have

## Consumer app configuration

Add to your app's `pyproject.toml`:

```toml
[[tool.uv.index]]
name = "hes-internal"
url = "https://VssSessionToken@pkgs.dev.azure.com/<org>/<project>/_packaging/<feed>/pypi/simple/"
default = false
explicit = true

[tool.uv.sources]
hestia = { index = "hes-internal" }

[tool.uv]
keyring-provider = "subprocess"
```

The `VssSessionToken@` prefix in the URL is required — uv passes the URL username to
`keyring get`, and `VssSessionToken` is the username this backend recognises.
