Metadata-Version: 2.3
Name: winwin-vault
Version: 0.1.0
Summary: Add your description here
Author: Ye Wenbin
Author-email: Ye Wenbin <yewenbin@brandct.com>
Requires-Dist: hvac>=2.0,<3.0
Requires-Dist: pytest>=8.0 ; extra == 'dev'
Requires-Dist: ruff>=0.15 ; extra == 'dev'
Requires-Python: >=3.11
Provides-Extra: dev
Description-Content-Type: text/markdown

# winwin-vault

[![PyPI version](https://img.shields.io/pypi/v/winwin-vault)](https://pypi.org/project/winwin-vault/)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

A read-only Python client for HashiCorp Vault, with automatic token renewal and dynamic secret caching.

## Installation

```bash
pip install winwin-vault
```

## Quick Start

```python
from winwin_vault import VaultClient

# Uses VAULT_ADDR and auth method from environment
client = VaultClient.from_env()

# Read a KV v2 secret
secret = client.read_kv("config")
print(secret["api_key"])

# Read database credentials (cached with TTL)
creds = client.read_database_creds("my-role")
print(creds.username, creds.password)

# Read Alicloud STS credentials (cached with TTL)
alicreds = client.read_alicloud_creds("my-role")
print(alicreds.access_key, alicreds.secret_key, alicreds.security_token)
```

## Authentication

`VaultClient.from_env()` auto-detects the auth method:

| Environment | Auth Method |
|------------|-------------|
| `VAULT_TOKEN` set | `EnvTokenAuth` |
| `~/.vault-token` present | `EnvTokenAuth` |
| Kubernetes ServiceAccount | `KubernetesAuth` |
| Vault Agent socket | `VaultAgentAuth` |

TLS is enforced for all auth methods except `VaultAgentAuth` (which communicates over a local Unix socket).

## Mount Points

Default mount points:

- KV v2: `secret`
- Database: `database`
- Alicloud: `alicloud`

Change via setters:

```python
client.set_kv_mount_point("internal")
client.set_database_mount_point("database")
client.set_alicloud_mount_point("alicloud")
```

## Exception Handling

```python
from winwin_vault import VaultClient, VaultClientError, VaultSecretNotFoundError

try:
    secret = client.read_kv("config")
except VaultSecretNotFoundError:
    print("Secret not found")
except VaultClientError as e:
    print(f"Vault error: {e}")
```

## License

MIT License — see [LICENSE](LICENSE) file to be added.
