Metadata-Version: 2.4
Name: envy-secrets
Version: 2.2.0
Summary: Git for your .env files - Secure environment variable management with encryption
Project-URL: Homepage, https://github.com/KRISHNA-JAIN15/ENVY
Project-URL: Documentation, https://github.com/KRISHNA-JAIN15/ENVY#readme
Project-URL: Repository, https://github.com/KRISHNA-JAIN15/ENVY
Project-URL: Issues, https://github.com/KRISHNA-JAIN15/ENVY/issues
Author-email: Krishna Jain <krishnajain1502@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: cli,devops,dotenv,encryption,env,environment,secrets,security
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Requires-Dist: argon2-cffi<24.0.0,>=23.1.0
Requires-Dist: cryptography<43.0.0,>=41.0.0
Requires-Dist: keyring<26.0.0,>=24.0.0
Requires-Dist: pynacl<2.0.0,>=1.5.0
Requires-Dist: pyyaml<7.0.0,>=6.0.0
Requires-Dist: requests<3.0.0,>=2.28.0
Requires-Dist: rich<14.0.0,>=13.0.0
Requires-Dist: typer[all]<1.0.0,>=0.9.0
Provides-Extra: dev
Requires-Dist: black>=23.0.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

# 🔐 Envy

**Git for your .env files** — Enterprise-grade secret management with Zero-Knowledge End-to-End Encryption, profile inheritance, schema validation, and a built-in web dashboard.

[![PyPI version](https://badge.fury.io/py/envy-secrets.svg)](https://pypi.org/project/envy-secrets/)
[![Python Version](https://img.shields.io/pypi/pyversions/envy-secrets.svg)](https://pypi.org/project/envy-secrets/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Downloads](https://pepy.tech/badge/envy-secrets)](https://pepy.tech/project/envy-secrets)

[Installation](#installation) • [Quick Start](#quick-start) • [Features](#-features-overview) • [Commands](#-command-reference) • [Architecture](#-zero-knowledge-e2ee-architecture) • [Contributing](#-contributing)

</div>

---

## 📋 Table of Contents

- [Why Envy?](#-why-envy)
- [Features Overview](#-features-overview)
- [Tech Stack](#-tech-stack)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Command Reference](#-command-reference)
  - [Core Commands](#core-commands)
  - [Profile Commands](#profile-commands)
  - [Schema Validation](#schema-validation)
  - [Git Hooks](#git-hooks)
  - [Cloud & Team Commands](#cloud--team-commands)
  - [Web Dashboard](#web-dashboard)
- [Zero-Knowledge E2EE Architecture](#-zero-knowledge-e2ee-architecture)
- [Anti-Phishing Protection](#-anti-phishing-protection)
- [Profile Inheritance](#-profile-inheritance)
- [Schema Validation & Type-Safety](#-schema-validation--type-safety)
- [Log Masking](#-log-masking)
- [Envy Blame](#-envy-blame)
- [Pre-commit Hook Integration](#-pre-commit-hook-integration)
- [Local Web Dashboard (Envy UI)](#-local-web-dashboard-envy-ui)
- [VS Code Extension](#-vs-code-extension)
- [Use Cases](#-use-cases)
- [Contributing](#-contributing)
- [License](#-license)

---

## 💡 Why Envy?

Every development team has the same problem: **managing secrets is painful.** `.env` files are plaintext, easy to leak, and impossible to share securely. Existing tools either require a third-party SaaS provider that can read your secrets, or they're so complex they need a dedicated DevOps engineer to set up.

**Envy is different.** It's a CLI-first tool that works like Git — you initialize it in your project directory, encrypt your secrets locally, and sync them with your team through Envy Cloud. The critical difference is that **Envy Cloud never sees your secrets.** Every piece of sensitive data is encrypted on your machine before it ever leaves, using the same cryptographic primitives used by Signal and 1Password.

Envy replaces:
- Plaintext `.env` files ❌
- Shared password vaults with copy-paste workflows ❌
- Third-party secret managers that require you to trust their servers ❌

With:
- **AES-256-GCM** encrypted local storage ✅
- **Zero-Knowledge End-to-End Encryption** for cloud sync ✅
- A single CLI command (`envy run`) that injects secrets into memory without ever touching disk ✅

---

## ✨ Features Overview

| Feature | Description |
|---------|-------------|
| 🔐 **AES-256-GCM Encryption** | All secrets are encrypted at rest using authenticated encryption (AEAD) |
| 🏗️ **Zero-Knowledge E2EE** | Cloud sync where the server mathematically *cannot* read your secrets |
| 🎣 **Anti-Phishing (WebAuthn + PRF)** | True passwordless E2EE: Biometric passkey unlocks the vault via PRF extension. No master password needed. |
| 📁 **Profile Management** | Multiple environments (`dev`, `staging`, `prod`) with one-click switching |
| 🔗 **Profile Inheritance** | `staging` can inherit from `prod` — only store overrides |
| 🛡️ **Schema Validation** | Enforce types, patterns, and per-profile rules on all secrets |
| 🎭 **Log Masking** | `envy run` intercepts stdout/stderr and masks secret values with `********` |
| 📜 **Envy Blame** | Git-blame-style audit trail showing who changed what, when |
| 🖥️ **Web Dashboard** | Beautiful local dark-mode UI for managing 100+ variables visually |
| ☁️ **Cloud Sync** | Push, pull, and clone secrets across your team |
| 💻 **Native VS Code SCM** | Envy acts as a native Source Control provider in VS Code, showing local vs remote changes |

---

## 🛠️ Tech Stack

Envy is a full-stack application spanning a Python CLI, a Node.js API, a React web dashboard, and a self-contained local UI — all unified by a Zero-Knowledge cryptographic core.

### CLI (Python)

| Component | Technology | Purpose |
|-----------|------------|----------|
| Framework | **Typer** + **Rich** | Command-line interface with beautiful terminal output |
| Encryption | **cryptography** (AES-256-GCM, X25519) | Local secret encryption and asymmetric key exchange |
| Key Derivation | **argon2-cffi** (Argon2id) | Derives encryption keys from the Master Password |
| Anti-Phishing | **SRP-6a** (pure Python, RFC 5054) | Zero-knowledge password proof for headless login |
| Browser Auth | **OAuth PKCE** (built-in `http.server`) | Opens browser for Passkey login, captures token via localhost callback |
| HTTP | **requests** | API communication with Envy Cloud |
| Keyring | **keyring** | Stores master key in OS keychain (Windows Credential Manager, macOS Keychain) |
| Local UI | **http.server** (built-in) | Self-contained web dashboard with zero dependencies |
| Build | **hatchling** | PEP 517 compliant Python package builder |
| CI/CD | **GitHub Actions** (OIDC Trusted Publishing) | Automated PyPI releases |

### Backend (Node.js)

| Component | Technology | Purpose |
|-----------|------------|----------|
| Framework | **Express.js 5** | REST API server |
| Database | **MongoDB** + **Mongoose** | User accounts, projects, encrypted secrets, activity logs |
| Auth (Passkeys) | **@simplewebauthn/server** | WebAuthn registration and authentication |
| Auth (SRP) | **secure-remote-password** | Server-side SRP-6a challenge-response |
| Auth (Tokens) | **jsonwebtoken** | JWT session tokens (7-day expiry) |
| Validation | **express-validator** | Request body validation |

### Frontend (React)

| Component | Technology | Purpose |
|-----------|------------|----------|
| Framework | **React** + **Vite** | Single-page application |
| Passkeys | **@simplewebauthn/browser** | WebAuthn registration/login from the browser |
| E2EE | **libsodium-wrappers** + **Web Crypto API** | Client-side X25519 key exchange and AES-256-GCM decryption |
| Styling | **CSS** | Custom design system with dark mode |

### Cryptographic Primitives

| Layer | Algorithm | Standard | Why |
|-------|-----------|----------|-----|
| Symmetric Encryption | **AES-256-GCM** | NIST SP 800-38D | AEAD cipher — encrypts and authenticates in one step. Used by TLS 1.3. |
| Asymmetric Key Exchange | **X25519** (Curve25519) | RFC 7748 | Modern elliptic-curve Diffie-Hellman. Used by Signal, WireGuard, and TLS 1.3. |
| Key Derivation | **Argon2id** | RFC 9106 | Memory-hard KDF resistant to GPU/ASIC brute-force attacks. Winner of the Password Hashing Competition. |
| Anti-Phishing (Browser) | **WebAuthn / FIDO2** | W3C WebAuthn L2 | Cryptographic authentication tied to the domain name. Impossible to phish. |
| Anti-Phishing (Headless) | **SRP-6a** | RFC 5054 | Zero-knowledge password proof. The password never leaves the client, even over a compromised network. |
| Random Numbers | **os.urandom / CSPRNG** | NIST SP 800-90A | Cryptographically secure random number generation for keys, nonces, and salts. |

---

## Installation

```bash
# Install from PyPI
pip install envy-secrets
```

**PyPI:** https://pypi.org/project/envy-secrets/

**Requirements:** Python 3.10+

### Development Installation

```bash
# Clone the repository
git clone https://github.com/KRISHNA-JAIN15/ENVY.git
cd ENVY

# Create and activate virtual environment
python -m venv venv
.\venv\Scripts\Activate   # Windows
source venv/bin/activate   # Linux/macOS

# Install in development mode with dev dependencies
pip install -e ".[dev]"
```

---

## Quick Start

```bash
# 1. Initialize Envy in your project
envy init

# 2. Add some secrets
envy set DATABASE_URL=postgres://localhost/mydb
envy set API_KEY=sk-1234567890 --expires 30d
envy set PORT=3000 --profile prod

# 3. View your secrets
envy view                          # Active profile (masked)
envy view --profile prod --show    # Show actual values

# 4. Run your app with secrets injected into memory (BEST PRACTICE!)
envy run dev -- npm start
envy run prod -- python app.py

# 5. Open the visual dashboard
envy ui

# 6. Sync with your team via Envy Cloud
envy cloud login
envy cloud push
```

---

## 📖 Command Reference

### Core Commands

| Command | Description |
|---------|-------------|
| `envy init` | Initialize Envy in the current directory. Creates `.envy/` with AES-256-GCM encryption keys and default profiles (`dev`, `staging`, `prod`). Automatically updates `.gitignore`. |
| `envy set KEY=VALUE` | Encrypt and store a secret. Supports `--profile`, `--expires`, and `--desc` flags. Validates against schema rules if `envy.schema.json` exists. |
| `envy get KEY` | Retrieve a secret value. Use `--show` to reveal the plaintext (masked by default). |
| `envy delete KEY` | Delete a secret from a profile. Requires `--force` or interactive confirmation. |
| `envy view` | Display all secrets in a table with Key, Value (masked), Source (own/inherited), and Status (expired/stale). Use `--show` to reveal values, `--json` for JSON output. |
| `envy run <profile> -- <cmd>` | **Gold standard for security.** Injects decrypted secrets into the subprocess environment. Secrets live only in memory — never written to disk. Automatically masks secret values leaked in stdout/stderr. |
| `envy export` | Generate a plaintext `.env` file. ⚠️ Less secure than `envy run`. |
| `envy import <file>` | Import variables from an existing `.env` file. Use `--merge` to add to existing secrets. |
| `envy capture` | Capture environment variables from the current shell session. Filters out system variables like `PATH`, `HOME`, etc. |
| `envy diff <source> <target>` | Compare two profiles to find missing, extra, or different keys. Prevents "works on my machine" errors. |
| `envy check` | Health check — find expired, expiring-soon, and stale secrets. Returns exit code 1 if issues are found (great for CI). |
| `envy blame <KEY>` | Show the full change history for a specific key from Envy Cloud. Displays user, action, environment, source (CLI/web), and timestamp. |
| `envy status` | Show a summary of the project: active profile, total profiles, schema rules, and encryption status. |
| `envy version` | Print the current Envy version. |
| `envy shell` | Print shell export commands. Usage: `eval $(envy shell)` |
| `envy ui` | Launch a local web dashboard at `http://localhost:8888`. |

### Profile Commands

| Command | Description |
|---------|-------------|
| `envy profile list` | List all profiles with secret counts and inheritance info. |
| `envy profile create <name>` | Create a new profile. Use `--extends <parent>` for inheritance. |
| `envy profile delete <name>` | Delete a profile and all its secrets. |
| `envy profile switch <name>` | Switch the active profile. |
| `envy profile copy <src> <dst>` | Clone all secrets from one profile to another. |

### Schema Validation

| Command | Description |
|---------|-------------|
| `envy schema show` | Display the current `envy.schema.json` rules. |
| `envy schema init` | Auto-generate a schema from your existing secrets. |
| `envy schema validate` | Validate all secrets in the active profile against the schema. |

### Git Hooks

| Command | Description |
|---------|-------------|
| `envy hooks install` | Install a Git pre-commit hook that warns when secrets are modified but not pushed to cloud. |
| `envy hooks uninstall` | Remove the Envy pre-commit hook. |

### Cloud & Team Commands

| Command | Description |
|---------|-------------|
| `envy cloud login` | Authenticate with Envy Cloud. |
| `envy cloud logout` | Clear saved credentials. |
| `envy cloud status` | Show the currently logged-in user. |
| `envy cloud clone <slug>` | Clone a project's secrets from the cloud. Auto-initializes Envy if needed. |
| `envy cloud push` | Push all local profiles to the cloud. Use `--profile <name>` to push a single profile. Use `--message <msg>` to add a commit-style message. |
| `envy cloud remote` | Show, add (`envy cloud remote add <slug>`), or remove the remote project origin. Validates access permissions. |
| `envy cloud activity` | View a git-style feed of recent activity for the linked cloud project. |

### Web Dashboard

| Command | Description |
|---------|-------------|
| `envy ui` | Launch on default port `8888` and auto-open browser. |
| `envy ui --port 3000` | Use a custom port. |
| `envy ui --no-open` | Start the server without opening the browser. |

---

## 🔐 Zero-Knowledge E2EE Architecture

Envy v2 implements a complete Zero-Knowledge End-to-End Encryption system. **The server never sees your secrets or your private key.** Here is how every layer works:

### 1. User Account Creation (Key Derivation)

When a user signs up (`envy cloud register`):

1. The CLI asks for a **Master Password**.
2. The CLI stretches the password into a 256-bit **Account Key** using **Argon2id** — the winner of the Password Hashing Competition and the current gold standard for key derivation.
3. The CLI generates an **X25519 asymmetric keypair** (a Public Key and a Private Key).
4. The CLI encrypts the Private Key using the Account Key with **AES-256-GCM**.
5. **What is sent to the server:** The plaintext Public Key, the *encrypted* Private Key, and the key salt. The Master Password and Account Key **never leave your computer**.

### 2. Project Initialization (`envy init`)

1. The CLI generates a random **256-bit Project Master Key** (symmetric, AES-256-GCM).
2. All local `.env` variables are encrypted using this Project Master Key.
3. The key is stored locally in `.envy/master.key` and added to `.gitignore`.

### 3. Pushing to the Cloud (`envy cloud push`)

Instead of decrypting secrets before sending them:

1. The CLI sends the secrets **still encrypted** with the Project Master Key.
2. To allow the cloud to store the Project Master Key safely, the CLI fetches the user's **Public Key** from the server.
3. The CLI encrypts the Project Master Key using the user's Public Key (X25519 sealed box).
4. **What is sent to the server:** The encrypted secrets blob + the encrypted Project Master Key. The server holds your data, but it is **mathematically impossible** for the server to read it.

### 4. Team Sharing (Adding a Teammate)

How do you securely share secrets if the server can't read them?

1. Admin runs `envy team add teammate@email.com`.
2. The CLI fetches the **teammate's Public Key** from the server.
3. The CLI takes the local Project Master Key and encrypts a copy of it using the **teammate's Public Key**.
4. The CLI pushes this new wrapped key to the server.
5. When the teammate runs `envy cloud clone`, they download the encrypted secrets and their specific encrypted copy of the Project Master Key. They decrypt the Project Master Key using their own Private Key, then decrypt the secrets.

### Cryptographic Primitives

| Layer | Algorithm | Why |
|-------|-----------|-----|
| Symmetric Encryption | **AES-256-GCM** | AEAD cipher — encrypts and authenticates in one step. Faster and more secure than CBC mode. |
| Asymmetric Encryption | **X25519** (Curve25519) | Modern elliptic-curve key exchange. Faster and smaller than RSA. Used by Signal, WireGuard, and TLS 1.3. |
| Key Derivation | **Argon2id** | Memory-hard KDF resistant to GPU/ASIC attacks. Winner of the Password Hashing Competition. Falls back to PBKDF2-SHA256 (600k iterations) if `argon2-cffi` is unavailable. |

> **Note:** The React web frontend mirrors the CLI's cryptographic capabilities using the Web Crypto API (`AES-256-GCM`, `PBKDF2`) and `libsodium-wrappers` (`X25519`). Keys are held in ephemeral memory refs and are never persisted to localStorage or cookies.

---

## 🎣 Anti-Phishing Protection & Passwordless E2EE

Envy implements **100% phishing-proof authentication** using two complementary protocols. No matter how a user logs in, their credentials are mathematically protected from interception.

### WebAuthn (Passkeys) + PRF — Primary Login & Vault Unlock

When you run `envy cloud login` or log in on the web dashboard, Envy uses **WebAuthn / FIDO2 Passkeys**. Passkeys are cryptographic credentials tied to the exact domain name (`envy.com`). 

**Passwordless E2EE via PRF:** Envy utilizes the cutting-edge **WebAuthn PRF (Pseudo-Random Function) extension**. When you authenticate with your passkey, the authenticator derives a deterministic 32-byte secret. Envy uses this secret (via HKDF) as a wrapping key to decrypt your E2EE private key. **This means you never have to type your Master Password to sync secrets** — your fingerprint/face ID unlocks your E2EE vault automatically.

**Supported Authenticators:** Apple TouchID, Windows Hello, Microsoft Authenticator, Google Password Manager, 1Password, YubiKey, and any FIDO2-compliant device.

**CLI Flow (OAuth PKCE):**
1. You run `envy cloud login`.
2. The CLI spins up a temporary `localhost` server and opens your browser.
3. You authenticate on the trusted domain via Passkey (biometric scan, QR code, etc.).
4. The browser redirects back to the CLI with the session token.
5. The CLI captures the token and you're logged in — no password was typed.

```bash
envy cloud login                  # Opens browser → Passkey authentication
```

### SRP-6a (Secure Remote Password) — Headless Fallback

For environments where a browser cannot be opened (SSH servers, CI/CD pipelines, Docker containers), Envy falls back to **SRP-6a** — a zero-knowledge proof protocol from RFC 5054.

**How it stops phishing:** Instead of sending your password to the server, the CLI uses your password to solve a mathematical challenge. Even if you accidentally connect to a malicious server, the server learns **absolutely nothing** about your password. The CLI also verifies the server's proof (`M2`) to confirm the server is authentic.

```bash
envy cloud login --headless       # SRP challenge-response (no browser needed)
```

**The 2-Step Handshake:**
1. **Step 1 (Challenge):** CLI sends email + ephemeral value `A`. Server responds with salt + ephemeral value `B`.
2. **Step 2 (Proof):** CLI computes proof `M1` using the password locally. Server verifies `M1` and responds with its own proof `M2`. CLI verifies `M2` to ensure the server is real.

At no point does the password leave the client. The server stores only a mathematical `verifier` (computed during registration), which cannot be reversed to recover the password.

### Vault Decryption (Always Local)

Whether you log in via Passkey or SRP, the server only handles **authentication** (proving who you are). The actual **decryption** of your secrets always requires your **Master Password** locally — the server never has access to it. This is the same security model used by 1Password and Bitwarden.

### Implementation Details

#### CLI Integration
- **`envy cloud register`**: Computes the SRP salt and verifier locally (your password is never sent). It generates an X25519 E2EE keypair, encrypts the private key using an Argon2id-derived key, and sends only the verifier and the encrypted key material to the server.
- **`envy cloud login`**: Defaults to the OAuth PKCE browser flow for Passkey authentication. The `--headless` flag triggers the 2-step SRP challenge-response handshake.

#### Frontend WebAuthn & SRP Integration
- **SRP Client (`srp.js`)**: A JavaScript SRP-6a client manages `SRPSession` and `generateVerifier` to ensure zero-knowledge authentication in the browser.
- **API endpoints (`api.js`)**: Replaced traditional login with `srpChallenge` and `srpVerify` endpoints, and added endpoints for WebAuthn authentication.
- **Auth Context (`AuthContext.jsx`)**: The `register()` function computes the SRP verifier locally. The `login()` function performs the 2-step SRP handshake. New `loginWithPasskey()` and `registerPasskey()` functions handle WebAuthn.
- **Auth UI**: `Login.jsx` features a two-tab UI: **Passkey** (default, phishing-proof) and **Master Password** (SRP, zero-knowledge). `Signup.jsx` uses SRP registration and clearly indicates that the "password never leaves your device."

---


## 🔗 Profile Inheritance

If you have 50 variables in `prod` and 49 of them are the same in `staging`, you shouldn't have to duplicate them all. With profile inheritance, you store only the overrides.

### How It Works

```bash
# Create a staging profile that inherits everything from prod
envy profile create staging --extends prod

# Override just the one key that's different
envy set DATABASE_URL=postgres://staging-db --profile staging
```

Now `staging` automatically inherits all 50 keys from `prod`, and only the `DATABASE_URL` override is stored in the `staging` profile. The `secrets.json` stays small and manageable.

### Viewing Inherited Secrets

```bash
envy view --profile staging
```

The table shows a **Source** column:
- `own` — the key is defined directly in this profile
- `← prod` — the key is inherited from the parent profile

### Circular Reference Protection

Envy walks the inheritance chain with cycle detection. If you accidentally create a circular dependency (`A extends B, B extends A`), it will stop and use only the keys it has already resolved.

---

## 🛡️ Schema Validation & Type-Safety

Plain `.env` files are just dumb strings. Envy lets you define strict rules for your secrets so that mistakes are caught **before** they reach production.

### Setting Up a Schema

Create an `envy.schema.json` file in your project root:

```json
{
  "variables": {
    "PORT": {
      "type": "integer",
      "required": true
    },
    "DATABASE_URL": {
      "type": "url",
      "required": true
    },
    "STRIPE_KEY": {
      "type": "string",
      "profiles": {
        "dev": { "pattern": "^sk_test_" },
        "prod": { "pattern": "^sk_live_" }
      }
    },
    "LOG_LEVEL": {
      "type": "string",
      "enum": ["debug", "info", "warn", "error"]
    },
    "APP_NAME": {
      "type": "string",
      "minLength": 3,
      "maxLength": 50
    }
  }
}
```

### Supported Validation Rules

| Rule | Description | Example |
|------|-------------|---------|
| `type` | Enforces a data type | `"integer"`, `"number"`, `"boolean"`, `"url"`, `"email"`, `"string"` |
| `required` | Key must exist in the profile | `true` / `false` |
| `pattern` | Regex pattern the value must match | `"^sk_live_"` |
| `enum` | Value must be one of a set | `["debug", "info", "warn"]` |
| `minLength` | Minimum string length | `3` |
| `maxLength` | Maximum string length | `128` |
| `profiles` | Per-profile overrides of any rule above | See the `STRIPE_KEY` example above |

### What Happens When Validation Fails

```bash
$ envy set STRIPE_KEY=sk_test_123 --profile prod
Schema Error: Value for STRIPE_KEY in profile 'prod' must match pattern: ^sk_live_
```

The CLI **blocks the operation** and does not save the secret.

### CLI Commands

```bash
envy schema show        # Display the current schema rules
envy schema init        # Auto-generate a schema from existing secrets
envy schema validate    # Validate all secrets in the active profile
```

---

## 🎭 Log Masking

When you run `envy run prod -- npm start`, Envy doesn't just inject the secrets — it **actively protects them from being leaked in logs.**

### How It Works

1. The subprocess is launched with `stdout` and `stderr` piped through Envy.
2. Two daemon threads read the output line-by-line in real time.
3. Every line is scanned for any secret value (≥ 4 characters long).
4. Matches are replaced with `********` before being printed to your terminal.

### Example

```bash
# If your app accidentally prints: "Connecting to postgres://admin:s3cret@db:5432"
# You see:                         "Connecting to ********"
```

### Controlling Log Masking

```bash
envy run prod -- npm start          # Masking ON (default)
envy run prod --no-mask -- npm start  # Masking OFF
```

---

## 📜 Envy Blame

Just like `git blame`, Envy Blame shows you exactly **who** changed a specific secret, **when** they changed it, and from **which source** (CLI or web dashboard).

### Usage

```bash
envy blame DATABASE_URL
```

### Output

```
┌──────────────────────────────────────────────────────────────┐
│                     📜 Blame: DATABASE_URL                   │
├────────┬──────────┬─────────┬──────┬────────┬───────────────┤
│ Commit │ User     │ Action  │ Env  │ Source │ When          │
├────────┼──────────┼─────────┼──────┼────────┼───────────────┤
│ a3f2c1 │ Krishna  │ updated │ prod │ cli    │ 2 hours ago   │
│ 8b1d4e │ Krishna  │ created │ prod │ web    │ 3 days ago    │
└────────┴──────────┴─────────┴──────┴────────┴───────────────┘
```

This works by querying the Envy Cloud activity log (`activities.js` model) for all events related to that specific key. It requires a remote to be configured (`envy cloud remote add <slug>`).

---

## 🪝 Pre-commit Hook Integration

A common failure mode: a developer adds a new package (like Stripe), creates a `STRIPE_KEY` in their local Envy, writes the code, and pushes — but forgets to run `envy cloud push`. The CI build breaks for everyone.

### Installation

```bash
envy hooks install
```

This creates a script in `.git/hooks/pre-commit`. Every time a developer runs `git commit`:

1. The hook checks if `.envy/secrets.json` has been modified in the staged files.
2. If it has, the hook **warns the developer** and asks them to push their secrets to the cloud before committing.
3. The commit proceeds, but the developer gets a clear, visible prompt.

### Uninstallation

```bash
envy hooks uninstall
```

This cleanly removes only the Envy portion of the pre-commit hook, leaving any other hooks intact.

---

## 🖥️ Local Web Dashboard (`envy ui`)

Managing 100+ environment variables in a terminal can be tedious. The `envy ui` command launches a **beautiful, full-screen dark-mode dashboard** on `localhost` where you can manage everything visually.

### How It's Built

The dashboard is completely self-contained inside the Python package. It uses Python's built-in `http.server` module — **zero external web framework dependencies** (no Flask, no FastAPI, no npm). The entire HTML, CSS, and JavaScript is embedded as a single inline template in `web_ui.py`.

### Launching the Dashboard

```bash
envy ui                    # Launch on port 8888, auto-open browser
envy ui --port 3000        # Use a custom port
envy ui --no-open          # Start without opening browser
```

### Dashboard Features

| Feature | Description |
|---------|-------------|
| **Profile Sidebar** | Lists all profiles with secret counts and inheritance indicators. Click to switch. |
| **Secrets Table** | View all keys in a sortable table. Click any value to toggle reveal/hide. |
| **Search** | Instant client-side filtering as you type. |
| **Add / Edit Secrets** | Modal dialog with key, value, and description fields. Schema validation runs on save. |
| **Delete Secrets** | One-click delete with confirmation prompt. |
| **Create Profiles** | Create new profiles with optional `--extends` inheritance. |
| **Visual Diff** | Side-by-side comparison of any two profiles. Missing keys are highlighted red, extra keys green, changed keys yellow. |
| **Dark Mode** | Premium design with Inter + JetBrains Mono fonts and glassmorphism accents. |

### Security

The server binds exclusively to `127.0.0.1` (localhost). It is **not accessible** from other machines on the network. All decryption happens server-side in the Python process — the browser receives already-decrypted values over the local loopback interface.

---

## 💻 VS Code Extension

Envy includes a rich, tightly integrated VS Code extension that brings secret management right into your editor.

### Features
- **Native Source Control (SCM)**: Envy acts as a native source control provider in VS Code, appearing right alongside Git. It shows "Local Changes (Unpushed)" and "Remote Changes (Unpulled)" with one-click Push, Pull, and Refresh buttons.
- **Secrets Explorer**: View and manage all your variables directly in the VS Code sidebar.
- **Activity Graph**: A Git-style activity feed in the sidebar showing who changed what, complete with color-coded commit-style badges.
- **Inline Hover & CodeLens**: Hover over `process.env.YOUR_KEY` in code to see the actual secret value (masked or unmasked).
- **Drift Detection**: The status bar warns you if your local secrets are out of sync with the cloud or if any variables are missing.
- **Remote Management**: Add remote origins (`envy cloud remote add`) directly from the command palette.

---

## 💡 Use Cases

### Local Development

```bash
# Developer A sets up the project
envy init
envy set DATABASE_URL=postgres://localhost/dev
envy set API_KEY=dev-key-123
envy run dev -- npm start

# Developer B clones and gets secrets
git clone repo && cd repo
envy cloud login
envy cloud clone myproject --env development
envy run dev -- npm start
```

### Multiple Environments with Inheritance

```bash
# Set up production with all variables
envy set DATABASE_URL=postgres://prod-db --profile prod
envy set REDIS_URL=redis://prod-cache --profile prod
envy set API_KEY=live-key-prod --profile prod

# Staging inherits everything, only override what's different
envy profile create staging --extends prod
envy set DATABASE_URL=postgres://staging-db --profile staging

# Run in either environment
envy run prod -- python app.py
envy run staging -- python app.py    # Gets prod's REDIS_URL and API_KEY automatically
```

### CI/CD Pipeline

```bash
# In your CI/CD pipeline (GitHub Actions, GitLab CI, etc.)
pip install envy-secrets
envy cloud login --email $ENVY_EMAIL --password $ENVY_PASSWORD
envy cloud clone myproject --env production
envy run prod -- npm run build
```

### Secret Rotation with Schema Enforcement

```bash
# Set up schema rules
envy schema init

# Set secrets with expiration
envy set API_KEY=old-key --expires 30d

# Check for expiring secrets (great for CI health checks)
envy check    # Returns exit code 1 if issues found

# Rotate the secret
envy set API_KEY=new-key --expires 30d
```

---

## 🔒 Security Best Practices

1. **Never commit `.envy/master.key`** — It's automatically added to `.gitignore` during `envy init`.
2. **Use `envy run` instead of `envy export`** — Secrets stay in process memory and are never written to a plaintext file on disk.
3. **Enable log masking** — It's on by default with `envy run`. Any secret value that leaks into stdout or stderr is replaced with `********`.
4. **Set expiration dates** — `envy set KEY=value --expires 30d` ensures you rotate secrets regularly.
5. **Run `envy check` in CI** — It returns a non-zero exit code if any secrets are expired or stale.
6. **Install pre-commit hooks** — `envy hooks install` warns developers when they forget to push new secrets.
7. **Use schema validation** — Define `envy.schema.json` to prevent staging keys from accidentally being used in production.

---

## File Structure

```
your-project/
├── .envy/
│   ├── master.key        # 🔑 AES-256-GCM encryption key (NEVER COMMIT!)
│   └── secrets.json      # 🔒 Encrypted secrets database (safe to commit)
├── envy.schema.json      # 📋 Optional schema validation rules (commit this)
├── .gitignore            # Auto-updated by envy init
└── ...
```

---

## ❓ FAQ

### How is this different from dotenv?

`dotenv` loads plaintext `.env` files. Envy encrypts secrets at rest with AES-256-GCM, supports multiple profiles, enforces schema validation, syncs via Zero-Knowledge E2EE, masks log output, and provides a visual web dashboard. It's an entire secret management platform, not just a file loader.

### Can I use this with my existing .env files?

Yes! Import your existing `.env` file and Envy will encrypt every variable:
```bash
envy import .env
```

### What happens if I lose my master key?

Without `.envy/master.key`, your local secrets cannot be decrypted. **Always back up this file securely.** If you use Envy Cloud, your secrets are also stored (encrypted) on the server and can be re-cloned by any team member.

### Is it safe to commit `.envy/secrets.json`?

Yes. The `secrets.json` file contains only AES-256-GCM encrypted ciphertext. Without the master key, it is computationally infeasible to decrypt.

### What encryption does Envy use?

Envy v2 uses **AES-256-GCM** (symmetric, AEAD), **X25519** (asymmetric key exchange, Curve25519), and **Argon2id** (key derivation). Fernet (AES-128-CBC) was fully removed in v2.0.

### Can I use this in production?

Absolutely. Use `envy run prod -- your-command` to inject secrets directly into your process without writing them to disk. The log masking feature ensures secrets don't leak into stdout/stderr.

### Does the web dashboard expose secrets to the network?

No. The `envy ui` server binds exclusively to `127.0.0.1` (localhost). It is not accessible from any other machine.

### If I have local changes and then clone a project, will my local changes be removed?

No, your local changes will **not** be removed!

When you run `envy cloud clone` (or "Clone Project" in the extension) in a workspace that already has local secrets, Envy performs a **merge**:

- **New remote keys** will be added to your local profile.
- **Conflicting keys** (keys that exist both locally and on the cloud) will be overwritten by the cloud's values.
- **Local-only keys** (keys you created locally that don't exist on the cloud) will be left completely untouched.

It effectively acts like a `git pull` with an auto-merge strategy favoring the remote.

*Note: The clone command will also automatically set the project as your remote origin if you haven't added one yet.*

### Is this compatible with Microsoft Authenticator / YubiKey / TouchID?
Yes, Envy uses standard WebAuthn for hardware-backed keys. It works out-of-the-box with Apple Touch ID, Windows Hello, YubiKeys, and authenticator apps like 1Password and Microsoft Authenticator.

### Why make a project "Public" if it only has environment variables?
This is a great question, because exposing actual secrets (like Database URLs or API keys) publicly is incredibly dangerous! However, having a "Public" visibility option for an env manager serves a few very powerful, specific use cases:

*   **Open Source Templates (`.env.example` replacement):** If you build an open-source project on GitHub, you can create a public Envy project that contains all the keys (and maybe safe default values) but keeps the real secrets blank. Contributors can just run `envy pull <project-id>` to instantly generate their local `.env` file with the correct schema, instead of copy-pasting from a `.env.example` file.
*   **Public Configuration:** Sometimes apps need to share non-sensitive configuration globally (e.g., `PUBLIC_API_URL`, feature flags, or theme settings). A public project allows client-side apps or community members to fetch this configuration without needing authentication.
*   **Forking Configurations:** Just like you fork a repo on GitHub, developers could "Fork" a public Envy project to instantly get the base configuration for a popular framework (like a Next.js starter kit) copied into their own private workspace.

### How does Envy Authentication work? What does `~/.envy_cloud.json` store?

It stores a simple plain-text JSON object that contains the session token given to you by the server, along with some basic profile information to display in the UI. It looks exactly like this:

```json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX...",
  "email": "your.email@example.com",
  "name": "Your Name",
  "api_url": "http://localhost:3000"
}
```
*(Note: It does **not** store your master password or any cryptographic keys. It only stores the session token!)*

### Is the location of `.envy_cloud.json` fixed?

Yes. The Python code explicitly saves it to `os.path.expanduser("~/.envy_cloud.json")`. The `~` symbol always resolves to your operating system's global user home directory (e.g., `C:\Users\jaink\` on Windows, or `/Users/jaink/` on a Mac).

### How does this work if Envy is installed inside a Python `venv`?

It works perfectly, and this fixed location is actually the secret to why it works so well!

Because the location is hardcoded to your OS global home directory (`~`), it completely ignores virtual environments. If you create 5 different Python projects, with 5 different isolated `venv`s, and install envy inside all of them, they will all look at your global `~/.envy_cloud.json`.

This means you can log in using one `venv` (or the VS Code extension), and all the other `venv`s on your computer will instantly be logged in too. You only ever have one global identity across your entire computer, exactly like `git`!

---

## 🤝 Contributing

We welcome contributions! Here's how to get started:

### Setting Up

```bash
git clone https://github.com/KRISHNA-JAIN15/ENVY.git
cd ENVY
python -m venv venv
source venv/bin/activate        # Linux/macOS
.\venv\Scripts\Activate         # Windows
pip install -e ".[dev]"
```

### Running Tests

```bash
pytest
```

### Code Style

```bash
black .
ruff check .
```

### Contribution Guidelines

1. **Fork the repository** and create a feature branch.
2. **Make your changes** with clear, descriptive commit messages.
3. **Add tests** for new features.
4. **Ensure all tests pass** with `pytest`.
5. **Format your code** with `black` and `ruff`.
6. **Submit a pull request** with a clear description of what you changed and why.

### Report Issues

Found a bug or have a feature request? [Open an issue](https://github.com/KRISHNA-JAIN15/ENVY/issues) on GitHub.

---

## 📄 License

MIT License — see the [LICENSE](LICENSE) file for details.

---

<div align="center">

**Made with ❤️ by [Krishna Jain](https://github.com/KRISHNA-JAIN15)**

⭐ Star us on [GitHub](https://github.com/KRISHNA-JAIN15/ENVY) • 🐦 Follow updates

[Report Bug](https://github.com/KRISHNA-JAIN15/ENVY/issues) • [Request Feature](https://github.com/KRISHNA-JAIN15/ENVY/issues) • [Documentation](https://github.com/KRISHNA-JAIN15/ENVY#readme)

</div>
