Prepare npm publish with README and MIT license
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 boxpositron
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
189
README.md
Normal file
189
README.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# envsitter
|
||||
|
||||
Safely inspect and match `.env` secrets **without ever printing values**.
|
||||
|
||||
`envsitter` is designed for LLM/agent workflows where you want to:
|
||||
|
||||
- List keys present in an env source (`.env` file or external provider)
|
||||
- Check whether a key’s value matches a candidate value you provide at runtime ("outside-in")
|
||||
- Do bulk matching (one candidate against many keys, or candidates-by-key)
|
||||
- Produce deterministic fingerprints for comparisons/auditing
|
||||
|
||||
## Security model (what this tool does and does not do)
|
||||
|
||||
- Values are read in-process for comparisons, but **never returned** by the library API and **never printed** by the CLI.
|
||||
- Deterministic matching uses **HMAC-SHA-256** with a local pepper.
|
||||
- This avoids publishing raw SHA-256 hashes that are easy to dictionary-guess.
|
||||
- Candidate secrets should be passed via stdin (`--candidate-stdin`) to avoid shell history.
|
||||
|
||||
Non-goals:
|
||||
|
||||
- This tool is not a secret manager.
|
||||
- This tool does not encrypt or relocate `.env` values; it operates on sources in-place.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install envsitter
|
||||
```
|
||||
|
||||
Or run the CLI without installing globally:
|
||||
|
||||
```bash
|
||||
npx envsitter keys --file .env
|
||||
```
|
||||
|
||||
## Pepper (required for deterministic fingerprints)
|
||||
|
||||
`envsitter` uses a local "pepper" as the HMAC key.
|
||||
|
||||
Resolution order:
|
||||
|
||||
1. `process.env.ENVSITTER_PEPPER` (or `ENV_SITTER_PEPPER`)
|
||||
2. Pepper file at `.envsitter/pepper` (auto-created if missing)
|
||||
|
||||
The pepper file is created with mode `0600` when possible, and `.envsitter/` is gitignored.
|
||||
|
||||
## CLI usage
|
||||
|
||||
### List keys
|
||||
|
||||
```bash
|
||||
envsitter keys --file .env
|
||||
```
|
||||
|
||||
Filter by key name (regex):
|
||||
|
||||
```bash
|
||||
envsitter keys --file .env --filter-regex "/(KEY|TOKEN|SECRET)/i"
|
||||
```
|
||||
|
||||
### Fingerprint a single key
|
||||
|
||||
```bash
|
||||
envsitter fingerprint --file .env --key OPENAI_API_KEY
|
||||
```
|
||||
|
||||
Outputs JSON containing the key’s fingerprint and metadata (never the value).
|
||||
|
||||
### Match a candidate against a single key (recommended via stdin)
|
||||
|
||||
```bash
|
||||
node -e "process.stdout.write('candidate-secret')" \
|
||||
| envsitter match --file .env --key OPENAI_API_KEY --candidate-stdin --json
|
||||
```
|
||||
|
||||
Exit codes:
|
||||
|
||||
- `0` match found
|
||||
- `1` no match
|
||||
- `2` error/usage
|
||||
|
||||
### Match one candidate against multiple keys
|
||||
|
||||
```bash
|
||||
node -e "process.stdout.write('candidate-secret')" \
|
||||
| envsitter match --file .env --keys OPENAI_API_KEY,ANTHROPIC_API_KEY --candidate-stdin --json
|
||||
```
|
||||
|
||||
### Match one candidate against all keys
|
||||
|
||||
```bash
|
||||
node -e "process.stdout.write('candidate-secret')" \
|
||||
| envsitter match --file .env --all-keys --candidate-stdin --json
|
||||
```
|
||||
|
||||
### Match candidates-by-key (bulk assignment)
|
||||
|
||||
Provide a JSON object mapping key -> candidate value.
|
||||
|
||||
```bash
|
||||
envsitter match-by-key --file .env \
|
||||
--candidates-json '{"OPENAI_API_KEY":"sk-...","ANTHROPIC_API_KEY":"sk-..."}'
|
||||
```
|
||||
|
||||
For safer input, pass the JSON via stdin:
|
||||
|
||||
```bash
|
||||
cat candidates.json | envsitter match-by-key --file .env --candidates-stdin
|
||||
```
|
||||
|
||||
### Scan for value shapes (no values returned)
|
||||
|
||||
```bash
|
||||
envsitter scan --file .env --detect jwt,url,base64
|
||||
```
|
||||
|
||||
Optionally restrict which keys to scan:
|
||||
|
||||
```bash
|
||||
envsitter scan --file .env --keys-regex "/(JWT|URL)/" --detect jwt,url
|
||||
```
|
||||
|
||||
## Library API
|
||||
|
||||
### Basic usage
|
||||
|
||||
```ts
|
||||
import { EnvSitter } from 'envsitter';
|
||||
|
||||
const es = EnvSitter.fromDotenvFile('.env');
|
||||
|
||||
const keys = await es.listKeys();
|
||||
const fp = await es.fingerprintKey('OPENAI_API_KEY');
|
||||
const match = await es.matchCandidate('OPENAI_API_KEY', 'candidate-secret');
|
||||
```
|
||||
|
||||
### Bulk matching
|
||||
|
||||
```ts
|
||||
import { EnvSitter } from 'envsitter';
|
||||
|
||||
const es = EnvSitter.fromDotenvFile('.env');
|
||||
|
||||
// One candidate tested against a set of keys
|
||||
const matches = await es.matchCandidateBulk(['OPENAI_API_KEY', 'ANTHROPIC_API_KEY'], 'candidate-secret');
|
||||
|
||||
// Candidates-by-key
|
||||
const byKey = await es.matchCandidatesByKey({
|
||||
OPENAI_API_KEY: 'sk-...',
|
||||
ANTHROPIC_API_KEY: 'sk-...'
|
||||
});
|
||||
```
|
||||
|
||||
### External sources (hooks)
|
||||
|
||||
You can load dotenv-formatted output from another tool/secret provider:
|
||||
|
||||
```ts
|
||||
import { EnvSitter } from 'envsitter';
|
||||
|
||||
const es = EnvSitter.fromExternalCommand('my-secret-provider', ['export', '--format=dotenv']);
|
||||
const keys = await es.listKeys();
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run typecheck
|
||||
npm test
|
||||
```
|
||||
|
||||
Run a single test file:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
node --test dist/test/envsitter.test.js
|
||||
```
|
||||
|
||||
Run a single test by name:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
node --test --test-name-pattern "outside-in" dist/test/envsitter.test.js
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT. See `LICENSE`.
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "envsitter",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
"description": "Safely inspect and match .env secrets without exposing values",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"envsitter": "./dist/cli.js"
|
||||
"envsitter": "dist/cli.js"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
Reference in New Issue
Block a user