# coreason-vault (The Safe)

![License](https://img.shields.io/badge/license-Prosperity%203.0-blue)
![CI Status](https://github.com/CoReason-AI/coreason-vault/actions/workflows/ci.yml/badge.svg)
![Code Style: Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)
[![Documentation](https://img.shields.io/badge/docs-Product%20Requirements-informational)](docs/product_requirements.md)

**The centralized guardian of secrets for the CoReason platform.**

`coreason-vault` manages secrets at rest and in memory, replacing legacy local encryption and unsafe environment variable practices with a robust, centralized Vault-based architecture.

## Mission

*   **Secure Retrieval:** Fetch API keys and database credentials securely from HashiCorp Vault.
*   **Key Rotation & Leases:** Handle dynamic secrets with lease management.
*   **Encryption as a Service (EaaS):** Delegate encryption of sensitive user data to Vault's Transit Engine, ensuring the application never handles encryption keys.

## Features

*   **"The Safe" Philosophy:** Application code never sees long-lived credentials or performs its own encryption.
*   **Transit Engine Integration:** Replaces local `crypto.py` by offloading encryption/decryption to Vault.
*   **Just-in-Time Secrets:** Fetches secrets on demand with caching (TTL ~60s) to prevent API hammering.
*   **Dynamic Secrets:** Supports retrieval of dynamic secrets with lease information.
*   **Automated Authentication:** Seamlessly handles AppRole (local/VM) and Kubernetes (Prod) authentication with auto-renewal.
*   **Resilience:** Built-in retries and circuit breaking for Vault connection issues.

## Installation

```bash
pip install coreason-vault
```

## Usage

```python
from coreason_vault import VaultManager, VaultConfig
from coreason_vault.exceptions import SecretNotFoundError

# 1. Initialize
# Automatically reads configuration from environment variables:
# VAULT_ADDR, VAULT_ROLE_ID/SECRET_ID (or K8S Auth), etc.
config = VaultConfig()
vault = VaultManager(config)

# 2. Fetch Secret (KV Version 2)
try:
    # Fetches from 'secret/data/coreason/services/openai' (mount point defaults to 'secret')
    creds = vault.secrets.get("coreason/services/openai")
    print(f"Using API Key: {creds['api_key'][:4]}...")
except SecretNotFoundError:
    print("Fatal: OpenAI credentials missing")

# 3. Encrypt Sensitive Data (Transit Engine)
# The app never sees the encryption key. Vault handles the cryptography.
ciphertext = vault.cipher.encrypt(
    plaintext="Sensitive Patient Data",
    key_name="patient-data-key",
    context="user_123"  # Optional: Key derivation context for extra security
)
print(f"Stored in DB: {ciphertext}")
# Output example: vault:v1:QmF...

# 4. Decrypt Data
original_plaintext = vault.cipher.decrypt(
    ciphertext=ciphertext,
    key_name="patient-data-key",
    context="user_123"
)
print(f"Decrypted: {original_plaintext}")
```

## Configuration

The library uses `pydantic-settings` to load configuration from environment variables.

| Variable | Description | Default |
| :--- | :--- | :--- |
| `VAULT_ADDR` | **Required.** The URL of the Vault server. | - |
| `VAULT_NAMESPACE` | The Vault namespace (Enterprise/Cloud). | `None` |
| `VAULT_ROLE_ID` | AppRole Role ID. | `None` |
| `VAULT_SECRET_ID` | AppRole Secret ID. | `None` |
| `VAULT_K8S_ROLE` | Kubernetes Role Name (for K8s auth). | `None` |
| `KUBERNETES_SERVICE_ACCOUNT_TOKEN` | K8s SA Token (injected by K8s). | `None` |
| `VAULT_MOUNT_POINT` | KV v2 Mount Point. | `secret` |
| `VAULT_VERIFY_SSL` | Verify SSL certificates. | `True` |
| `VAULT_TOKEN_TTL` | Token validation interval in seconds. | `60` |

## License

This software is licensed under the **Prosperity Public License 3.0**.
Commercial use beyond a 30-day trial requires a separate license.
See [LICENSE](LICENSE) for details.
