npm package: @phantasm0009/secure-env
Description: End-to-end secret management with encrypted .env files, git protection, and runtime validation
Author: phantasm0009
Latest version: 1.0.3

# @phantasm0009/secure-env

🔐 End-to-end secret management for Node.js applications with encrypted `.env` files, git protection, and runtime validation.

## Features

- 🔐 **Encrypted Environment Files** - AES-256-GCM encryption with secure key generation
- 🛡️ **Git Protection** - Pre-commit hooks prevent accidental commits of sensitive files
- ✅ **Runtime Validation** - Zod-like schema validation for environment variables
- ☁️ **Cloud KMS Support** - AWS KMS and Google Cloud KMS integration
- 🚀 **Zero Dependencies** - Production-ready with Node.js 18+ built-ins
- 📦 **Multiple Formats** - Support for `.env.local`, `.env.production`, etc.

## Installation

```bash
npm install @phantasm0009/secure-env
```

## Quick Start

### 1. Basic Setup

Create a `.env` file with your secrets:

```bash
# .env
API_KEY=your-secret-api-key-here
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
DEBUG=true
PORT=3000
```

### 2. Encrypt Your Environment File

```bash
# Generate encryption key and encrypt .env
npx secure-env encrypt

# This creates:
# - .env.key (keep this secret!)
# - .env.encrypted (safe to commit)
```

### 3. Setup Git Protection

```bash
# Install pre-commit hooks and update .gitignore
npx secure-env setup-git
```

### 4. Load and Validate in Your Application

```javascript
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');

// Define validation schema
const schema = envSchema({
  PORT: number().min(3000).max(8000),
  API_KEY: string().length(32),
  DEBUG: boolean(),
  DATABASE_URL: string().regex(/^postgresql:\/\//)
});

// Load and validate environment
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);

console.log('Validated environment:', env);
// Output: { PORT: 3000, API_KEY: 'your-secret-api-key-here', DEBUG: true, ... }
```

## CLI Commands

### Encryption Commands

```bash
# Encrypt .env file (creates .env.encrypted and .env.key)
secure-env encrypt

# Encrypt specific file
secure-env encrypt .env.production

# Decrypt to .env
secure-env decrypt

# Decrypt to specific file
secure-env decrypt --output .env.development

# Generate new encryption key
secure-env generate-key

# Use custom key path
secure-env encrypt --key-path ./keys/production.key
```

### Validation Commands

```bash
# Check if required variables are present
secure-env check PORT API_KEY DATABASE_URL

# Validate against schema file
secure-env validate schema.js
```

### Git Protection

```bash
# Setup git hooks and .gitignore protection
secure-env setup-git
```

## API Reference

### SecureEnv Class

```javascript
const { SecureEnv } = require('@phantasm0009/secure-env');
const secureEnv = new SecureEnv();

// Encryption/Decryption
secureEnv.encryptFile('.env', '.env.encrypted');
secureEnv.decryptFile('.env.encrypted', '.env');

// Key management
const key = secureEnv.generateKey();
secureEnv.saveKey(key, '.env.key');

// Load with validation
const env = secureEnv.load(schema, { override: true });

// Setup git protection
secureEnv.setupGitProtection();
```

### Schema Validation

Build validation schemas with chainable methods:

```javascript
const { envSchema, string, number, boolean } = require('@phantasm0009/secure-env');

const schema = envSchema({
  // String validation
  API_KEY: string()
    .length(32)                    // Exact length
    .regex(/^[a-zA-Z0-9]+$/)      // Pattern matching
    
  USERNAME: string()
    .min(3)                       // Minimum length
    .max(20),                     // Maximum length
    
  // Number validation  
  PORT: number()
    .min(3000)                    // Minimum value
    .max(8000)                    // Maximum value
    .int(),                       // Must be integer
    
  TIMEOUT: number()
    .min(0),
    
  // Boolean validation
  DEBUG: boolean(),
  ENABLED: boolean()
});
```

### Environment Loading

```javascript
const { loadEnv } = require('@phantasm0009/secure-env');

// Load with options
const env = loadEnv({
  path: './config',        // Directory to search
  override: true,          // Override existing values
  debug: true             // Log loaded files
});
```

### Manual Validation

```javascript
const { validateEnv, checkRequired } = require('@phantasm0009/secure-env');

// Validate against schema
const validated = validateEnv(process.env, schema);

// Check required variables
const result = checkRequired(['API_KEY', 'DATABASE_URL']);
if (!result.valid) {
  console.error('Missing:', result.missing);
}
```

## Real-World Examples

### Express.js Application

```javascript
const express = require('express');
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');

// Define schema for your app
const schema = envSchema({
  PORT: number().min(3000).max(8000),
  NODE_ENV: string().regex(/^(development|production|test)$/),
  JWT_SECRET: string().min(32),
  DATABASE_URL: string().regex(/^postgresql:\/\//),
  REDIS_URL: string().regex(/^redis:\/\//),
  DEBUG: boolean()
});

// Load and validate environment
const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);

const app = express();

app.get('/', (req, res) => {
  res.json({ 
    message: 'Server running securely!',
    environment: env.NODE_ENV,
    debug: env.DEBUG 
  });
});

app.listen(env.PORT, () => {
  console.log(`Server running on port ${env.PORT}`);
});
```

### Next.js Application

```javascript
// next.config.js
const { SecureEnv, envSchema, string, number, boolean } = require('@phantasm0009/secure-env');

const schema = envSchema({
  NEXT_PUBLIC_API_URL: string().regex(/^https?:\/\//),
  DATABASE_URL: string(),
  NEXTAUTH_SECRET: string().min(32),
  NEXTAUTH_URL: string().regex(/^https?:\/\//),
  NODE_ENV: string().regex(/^(development|production|test)$/)
});

const secureEnv = new SecureEnv();
const env = secureEnv.load(schema);

module.exports = {
  env: {
    CUSTOM_KEY: env.NEXT_PUBLIC_API_URL,
  },
  // ... other Next.js config
};
```

### Docker Deployment

```dockerfile
# Dockerfile
FROM node:18-alpine

WORKDIR /app

# Copy package files
COPY package*.json ./
RUN npm ci --only=production

# Copy source code
COPY . .

# Decrypt environment file during build
RUN npx secure-env decrypt --output .env

# Start application
CMD ["npm", "start"]
```

```bash
# Build with encrypted env file
docker build -t myapp .

# Or mount key at runtime
docker run -v $(pwd)/.env.key:/app/.env.key myapp
```

### CI/CD Pipeline

```yaml
# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          
      - name: Install dependencies
        run: npm ci
        
      - name: Create encryption key
        run: echo "${{ secrets.ENV_KEY }}" > .env.key
        
      - name: Decrypt environment
        run: npx secure-env decrypt
        
      - name: Run tests
        run: npm test
        
      - name: Deploy
        run: npm run deploy
```

## File Hierarchy

The loader searches for environment files in this order (later files override earlier ones):

1. `.env`
2. `.env.local`
3. `.env.development` / `.env.production` / `.env.test`
4. `.env.development.local` / `.env.production.local` / `.env.test.local`

## Security Best Practices

### Key Management

```bash
# Generate strong keys for different environments
secure-env generate-key --key-path .env.development.key
secure-env generate-key --key-path .env.production.key

# Encrypt environment-specific files
secure-env encrypt .env.development --key-path .env.development.key
secure-env encrypt .env.production --key-path .env.production.key
```

### Git Protection

The git protection feature automatically:
- Prevents commits of `.env*` files
- Prevents commits of `*.key` files  
- Updates `.gitignore` with secure patterns
- Shows helpful error messages when protection is triggered

### Production Deployment

For production environments, consider using cloud KMS:

```javascript
const { createKMSProvider } = require('@phantasm0009/secure-env');

// AWS KMS
const kms = createKMSProvider('aws', {
  region: 'us-east-1',
  keyId: 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
});

// Google Cloud KMS  
const kms = createKMSProvider('google', {
  projectId: 'my-project',
  keyRingId: 'my-keyring',
  keyId: 'my-key'
});
```

## Error Handling

```javascript
const { SecureEnv } = require('@phantasm0009/secure-env');

try {
  const secureEnv = new SecureEnv();
  const env = secureEnv.load(schema);
  console.log('Environment loaded successfully');
} catch (error) {
  if (error.message.includes('Environment validation failed')) {
    console.error('❌ Configuration errors:');
    console.error(error.message);
    process.exit(1);
  }
  
  if (error.message.includes('Encryption key not found')) {
    console.error('❌ Missing encryption key. Run: npx secure-env generate-key');
    process.exit(1);
  }
  
  throw error;
}
```

## Advanced Usage

### Custom Validation Messages

```javascript
const schema = envSchema({
  EMAIL: string().regex(
    /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
    'Must be a valid email address'
  ),
  
  API_VERSION: string().regex(
    /^v\d+$/,
    'Must be in format v1, v2, etc.'
  ),
  
  PORT: number()
    .min(1024, 'Port must be above 1024')
    .max(65535, 'Port must be below 65535')
});
```

### Multiple Environment Files

```javascript
// Load specific environment configurations
const devEnv = loadEnv({ 
  path: './environments/development',
  debug: true 
});

const prodEnv = loadEnv({ 
  path: './environments/production',
  override: true 
});
```

### Schema Composition

```javascript
const baseSchema = envSchema({
  NODE_ENV: string().regex(/^(development|production|test)$/),
  DEBUG: boolean()
});

const databaseSchema = envSchema({
  DATABASE_URL: string().regex(/^postgresql:\/\//),
  DB_POOL_SIZE: number().min(1).max(20)
});

const apiSchema = envSchema({
  API_KEY: string().length(32),
  API_TIMEOUT: number().min(1000)
});

// Combine schemas
const fullSchema = envSchema({
  ...baseSchema,
  ...databaseSchema,
  ...apiSchema
});
```

## Testing

Run the test suite:

```bash
# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run specific test file
node --test test/encryption.test.js
```

## Troubleshooting

### Common Issues

**Q: "Encryption key not found" error**
```bash
# Generate a new key
npx secure-env generate-key

# Or specify custom path
npx secure-env generate-key --key-path ./custom/path/.env.key
```

**Q: Git hooks not working**
```bash
# Reinstall git hooks
npx secure-env setup-git

# Check if .git/hooks/pre-commit exists and is executable
ls -la .git/hooks/pre-commit
```

**Q: Validation errors**
```bash
# Check which variables are missing
npx secure-env check API_KEY DATABASE_URL PORT

# Validate against schema file
npx secure-env validate ./config/schema.js
```

**Q: Environment not loading**
```javascript
// Enable debug mode to see which files are loaded
const env = loadEnv({ debug: true });
```

## Contributing

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/amazing-feature`
3. Add tests for new functionality
4. Ensure all tests pass: `npm test`
5. Commit changes: `git commit -m 'Add amazing feature'`
6. Push to branch: `git push origin feature/amazing-feature`
7. Submit a pull request

## License

MIT License - see LICENSE file for details.

## Security

For security issues, please email security@phantasm0009.dev instead of using GitHub issues.

## Changelog

### v1.0.0
- Initial release
- AES-256-GCM encryption for .env files
- Git protection with pre-commit hooks
- Runtime validation with schema system
- CLI tools for encryption/decryption
- Cloud KMS integration support
- Comprehensive test suite