envpkt 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +507 -0
- package/dist/cli.js +2254 -0
- package/dist/index.d.ts +392 -0
- package/dist/index.js +1769 -0
- package/package.json +71 -0
- package/schemas/envpkt.schema.json +211 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Jordan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
# envpkt
|
|
2
|
+
|
|
3
|
+
[](https://github.com/jordanburke/envpkt/actions/workflows/node.js.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/envpkt)
|
|
5
|
+
|
|
6
|
+
Credential lifecycle and fleet management for AI agents.
|
|
7
|
+
|
|
8
|
+
**fnox handles access. envpkt handles awareness.** One file (`envpkt.toml`) answers five questions per credential: **What / Where / Why / When / How**.
|
|
9
|
+
|
|
10
|
+
## Why envpkt?
|
|
11
|
+
|
|
12
|
+
Secrets managers store values. envpkt stores _metadata about_ those values — what service each credential authenticates to, when it expires, how to rotate it, and why it exists. This gives AI agents (and their operators) a structured way to:
|
|
13
|
+
|
|
14
|
+
- Audit credential health across a fleet of agents
|
|
15
|
+
- Get warnings before secrets expire
|
|
16
|
+
- Detect stale or orphaned credentials
|
|
17
|
+
- Understand what capabilities each secret grants
|
|
18
|
+
- Automate rotation workflows
|
|
19
|
+
- Share secret metadata across agents via a central catalog
|
|
20
|
+
|
|
21
|
+
envpkt never touches secret values. It works alongside your existing secrets manager (Vault, fnox, CI variables, etc.).
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Install
|
|
27
|
+
npm install -g envpkt
|
|
28
|
+
|
|
29
|
+
# Auto-discover credentials from your shell environment
|
|
30
|
+
envpkt env scan
|
|
31
|
+
|
|
32
|
+
# Scaffold envpkt.toml from discovered credentials
|
|
33
|
+
envpkt env scan --write
|
|
34
|
+
|
|
35
|
+
# Audit credential health
|
|
36
|
+
envpkt audit
|
|
37
|
+
|
|
38
|
+
# Check for drift between envpkt.toml and live environment
|
|
39
|
+
envpkt env check
|
|
40
|
+
|
|
41
|
+
# Scan a directory tree of agents
|
|
42
|
+
envpkt fleet
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## The envpkt.toml File
|
|
46
|
+
|
|
47
|
+
Every project gets one `envpkt.toml` that describes its credentials. Here's a minimal example:
|
|
48
|
+
|
|
49
|
+
```toml
|
|
50
|
+
#:schema https://raw.githubusercontent.com/jordanburke/envpkt/main/schemas/envpkt.schema.json
|
|
51
|
+
|
|
52
|
+
version = 1
|
|
53
|
+
|
|
54
|
+
[meta.API_KEY]
|
|
55
|
+
service = "stripe"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
And a more complete one:
|
|
59
|
+
|
|
60
|
+
```toml
|
|
61
|
+
#:schema https://raw.githubusercontent.com/jordanburke/envpkt/main/schemas/envpkt.schema.json
|
|
62
|
+
|
|
63
|
+
version = 1
|
|
64
|
+
|
|
65
|
+
[agent]
|
|
66
|
+
name = "billing-service"
|
|
67
|
+
consumer = "agent"
|
|
68
|
+
description = "Payment processing agent"
|
|
69
|
+
capabilities = ["charge", "refund"]
|
|
70
|
+
expires = "2027-01-01"
|
|
71
|
+
|
|
72
|
+
[lifecycle]
|
|
73
|
+
stale_warning_days = 90
|
|
74
|
+
require_expiration = true
|
|
75
|
+
require_service = true
|
|
76
|
+
|
|
77
|
+
[meta.STRIPE_SECRET_KEY]
|
|
78
|
+
service = "stripe"
|
|
79
|
+
purpose = "Process customer payments and manage subscriptions"
|
|
80
|
+
capabilities = ["charges:write", "subscriptions:write"]
|
|
81
|
+
created = "2026-01-15"
|
|
82
|
+
expires = "2027-01-15"
|
|
83
|
+
rotation_url = "https://dashboard.stripe.com/apikeys"
|
|
84
|
+
source = "vault"
|
|
85
|
+
|
|
86
|
+
[meta.DATABASE_URL]
|
|
87
|
+
service = "postgres"
|
|
88
|
+
purpose = "Read/write access to the billing database"
|
|
89
|
+
capabilities = ["SELECT", "INSERT", "UPDATE"]
|
|
90
|
+
created = "2026-02-01"
|
|
91
|
+
expires = "2026-08-01"
|
|
92
|
+
rotation_url = "https://wiki.internal/runbooks/rotate-db-creds"
|
|
93
|
+
source = "vault"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
See [`examples/`](./examples/) for more configurations.
|
|
97
|
+
|
|
98
|
+
## Shared Secret Catalog
|
|
99
|
+
|
|
100
|
+
When multiple agents consume the same secrets, a **shared catalog** prevents metadata duplication. Define secret metadata once in a central file, then have each agent reference it.
|
|
101
|
+
|
|
102
|
+
### Catalog file (`infra/envpkt.toml`)
|
|
103
|
+
|
|
104
|
+
```toml
|
|
105
|
+
version = 1
|
|
106
|
+
|
|
107
|
+
[lifecycle]
|
|
108
|
+
stale_warning_days = 90
|
|
109
|
+
require_expiration = true
|
|
110
|
+
|
|
111
|
+
[meta.DATABASE_URL]
|
|
112
|
+
service = "postgres"
|
|
113
|
+
purpose = "Primary application database"
|
|
114
|
+
capabilities = ["SELECT", "INSERT", "UPDATE", "DELETE"]
|
|
115
|
+
rotation_url = "https://wiki.internal/runbooks/rotate-db"
|
|
116
|
+
source = "vault"
|
|
117
|
+
created = "2025-11-01"
|
|
118
|
+
expires = "2026-11-01"
|
|
119
|
+
|
|
120
|
+
[meta.REDIS_URL]
|
|
121
|
+
service = "redis"
|
|
122
|
+
purpose = "Caching and session storage"
|
|
123
|
+
created = "2025-11-01"
|
|
124
|
+
expires = "2026-11-01"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Agent file (`agents/pipeline/envpkt.toml`)
|
|
128
|
+
|
|
129
|
+
```toml
|
|
130
|
+
version = 1
|
|
131
|
+
catalog = "../../infra/envpkt.toml"
|
|
132
|
+
|
|
133
|
+
[agent]
|
|
134
|
+
name = "data-pipeline"
|
|
135
|
+
consumer = "agent"
|
|
136
|
+
secrets = ["DATABASE_URL", "REDIS_URL"]
|
|
137
|
+
|
|
138
|
+
# Optional: narrow the catalog definition for this agent
|
|
139
|
+
[meta.DATABASE_URL]
|
|
140
|
+
capabilities = ["SELECT"]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Resolve to a flat config
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
envpkt resolve -c agents/pipeline/envpkt.toml
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
This produces a self-contained config with catalog metadata merged in and agent overrides applied. The resolved output has no `catalog` reference — it's ready for deployment.
|
|
150
|
+
|
|
151
|
+
### Merge rules
|
|
152
|
+
|
|
153
|
+
- Each field in the agent's `[meta.KEY]` override **replaces** the catalog field (shallow merge)
|
|
154
|
+
- Omitted fields keep the catalog value
|
|
155
|
+
- `agent.secrets` is the source of truth for which keys the agent needs
|
|
156
|
+
|
|
157
|
+
## CLI Commands
|
|
158
|
+
|
|
159
|
+
### `envpkt init`
|
|
160
|
+
|
|
161
|
+
Generate an `envpkt.toml` template in the current directory.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
envpkt init # Basic template
|
|
165
|
+
envpkt init --from-fnox # Scaffold from fnox.toml
|
|
166
|
+
envpkt init --agent --name "my-agent" # Include agent identity
|
|
167
|
+
envpkt init --catalog "../infra/envpkt.toml" # Reference a shared catalog
|
|
168
|
+
envpkt init --agent --name "bot" --capabilities "read,write" --expires "2027-01-01"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### `envpkt audit`
|
|
172
|
+
|
|
173
|
+
Check credential health against lifecycle policies. Automatically resolves catalog references.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
envpkt audit # Table output
|
|
177
|
+
envpkt audit --format json # JSON output
|
|
178
|
+
envpkt audit --expiring 14 # Show secrets expiring within 14 days
|
|
179
|
+
envpkt audit --status expired # Filter by status
|
|
180
|
+
envpkt audit --strict # Exit non-zero on any non-healthy secret
|
|
181
|
+
envpkt audit -c path/to/envpkt.toml # Specify config path
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Exit codes: `0` = healthy, `1` = degraded, `2` = critical.
|
|
185
|
+
|
|
186
|
+
### `envpkt resolve`
|
|
187
|
+
|
|
188
|
+
Resolve catalog references and output a flat, self-contained config.
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
envpkt resolve -c agent.toml # Output resolved TOML to stdout
|
|
192
|
+
envpkt resolve -c agent.toml --format json # Output as JSON
|
|
193
|
+
envpkt resolve -c agent.toml -o resolved.toml # Write to file
|
|
194
|
+
envpkt resolve -c agent.toml --dry-run # Preview without writing
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Configs without a `catalog` field pass through unchanged.
|
|
198
|
+
|
|
199
|
+
### `envpkt fleet`
|
|
200
|
+
|
|
201
|
+
Scan a directory tree for `envpkt.toml` files and aggregate health.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
envpkt fleet # Scan current directory (depth 3)
|
|
205
|
+
envpkt fleet -d /opt/agents # Scan specific directory
|
|
206
|
+
envpkt fleet --depth 5 # Increase scan depth
|
|
207
|
+
envpkt fleet --format json # JSON output
|
|
208
|
+
envpkt fleet --status critical # Filter agents by health status
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### `envpkt inspect`
|
|
212
|
+
|
|
213
|
+
Display a structured view of an `envpkt.toml` file. Automatically resolves catalog references.
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
envpkt inspect # Current directory
|
|
217
|
+
envpkt inspect -c path/to/envpkt.toml # Specific file
|
|
218
|
+
envpkt inspect --format json # Raw JSON dump
|
|
219
|
+
envpkt inspect --resolved # Show resolved view (catalog merged)
|
|
220
|
+
envpkt inspect --secrets # Show secret values from env (masked)
|
|
221
|
+
envpkt inspect --secrets --plaintext # Show secret values in plaintext
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
The `--secrets` flag reads values from environment variables matching each secret key. By default values are masked (`pos•••••yapp`). Add `--plaintext` to display full values.
|
|
225
|
+
|
|
226
|
+
### `envpkt exec`
|
|
227
|
+
|
|
228
|
+
Run a pre-flight audit, inject secrets from fnox into the environment, then execute a command.
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
envpkt exec -- node server.js # Audit then run
|
|
232
|
+
envpkt exec --skip-audit -- npm start # Skip the audit
|
|
233
|
+
envpkt exec --strict -- ./deploy.sh # Abort if audit is not healthy
|
|
234
|
+
envpkt exec --profile staging -- ... # Use a specific fnox profile
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### `envpkt env scan`
|
|
238
|
+
|
|
239
|
+
Auto-discover credentials from your shell environment. Matches env vars against ~45 known services (exact name), ~13 generic suffix patterns (`*_API_KEY`, `*_SECRET`, `*_TOKEN`, etc.), and ~29 value shape patterns (`sk-*`, `ghp_*`, `AKIA*`, `postgres://`, etc.).
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
envpkt env scan # Table output with confidence icons
|
|
243
|
+
envpkt env scan --format json # JSON output
|
|
244
|
+
envpkt env scan --write # Write/append to envpkt.toml
|
|
245
|
+
envpkt env scan --dry-run # Preview TOML that would be written
|
|
246
|
+
envpkt env scan --include-unknown # Include vars with no inferred service
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Confidence levels:
|
|
250
|
+
|
|
251
|
+
- **High** (●) — exact name match or recognized value prefix
|
|
252
|
+
- **Medium** (◐) — generic suffix pattern with derived service name
|
|
253
|
+
|
|
254
|
+
### `envpkt env check`
|
|
255
|
+
|
|
256
|
+
Bidirectional drift detection between `envpkt.toml` and the live shell environment. Checks both directions: TOML keys missing from env, and credential-shaped env vars not tracked in TOML.
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
envpkt env check # Table output
|
|
260
|
+
envpkt env check --format json # JSON output
|
|
261
|
+
envpkt env check --strict # Exit non-zero on any drift
|
|
262
|
+
envpkt env check -c path/to/envpkt.toml # Specify config path
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### `envpkt shell-hook`
|
|
266
|
+
|
|
267
|
+
Output a shell function that runs `envpkt audit --format minimal` whenever you `cd` into a directory containing `envpkt.toml`.
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# Add to your .zshrc
|
|
271
|
+
eval "$(envpkt shell-hook zsh)"
|
|
272
|
+
|
|
273
|
+
# Add to your .bashrc
|
|
274
|
+
eval "$(envpkt shell-hook bash)"
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### `envpkt mcp`
|
|
278
|
+
|
|
279
|
+
Start the envpkt MCP server (stdio transport) for AI agent integration.
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
envpkt mcp
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## MCP Server
|
|
286
|
+
|
|
287
|
+
envpkt ships an [MCP](https://modelcontextprotocol.io/) server that exposes credential metadata to AI agents. Add it to your MCP client config:
|
|
288
|
+
|
|
289
|
+
```json
|
|
290
|
+
{
|
|
291
|
+
"mcpServers": {
|
|
292
|
+
"envpkt": {
|
|
293
|
+
"command": "envpkt",
|
|
294
|
+
"args": ["mcp"]
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Tools
|
|
301
|
+
|
|
302
|
+
| Tool | Description |
|
|
303
|
+
| ------------------ | ------------------------------------------------------- |
|
|
304
|
+
| `getPacketHealth` | Get overall health status with per-secret audit results |
|
|
305
|
+
| `listCapabilities` | List agent and per-secret capabilities |
|
|
306
|
+
| `getSecretMeta` | Get metadata for a specific secret by key |
|
|
307
|
+
| `checkExpiration` | Check expiration status and days remaining |
|
|
308
|
+
|
|
309
|
+
### Resources
|
|
310
|
+
|
|
311
|
+
| URI | Description |
|
|
312
|
+
| ----------------------- | --------------------------------- |
|
|
313
|
+
| `envpkt://health` | Current credential health summary |
|
|
314
|
+
| `envpkt://capabilities` | Agent and secret capabilities |
|
|
315
|
+
|
|
316
|
+
No secret values are ever exposed through the MCP server.
|
|
317
|
+
|
|
318
|
+
## Schema
|
|
319
|
+
|
|
320
|
+
envpkt.toml is validated against a JSON Schema. Editors with TOML + JSON Schema support will provide autocompletion and validation when the `#:schema` directive is present on line 1.
|
|
321
|
+
|
|
322
|
+
The schema is published at:
|
|
323
|
+
|
|
324
|
+
- npm: `envpkt/schema` (importable via package exports)
|
|
325
|
+
- GitHub: `schemas/envpkt.schema.json`
|
|
326
|
+
|
|
327
|
+
### Secret Metadata Fields
|
|
328
|
+
|
|
329
|
+
Each `[meta.<KEY>]` section describes a secret:
|
|
330
|
+
|
|
331
|
+
| Tier | Fields | Description |
|
|
332
|
+
| --------------- | ----------------------------------------------- | ----------------------------------------- |
|
|
333
|
+
| **Scan-first** | `service`, `expires`, `rotation_url` | Key health indicators for audit |
|
|
334
|
+
| **Context** | `purpose`, `capabilities`, `created` | Why this secret exists and what it grants |
|
|
335
|
+
| **Operational** | `rotates`, `rate_limit`, `model_hint`, `source` | Runtime and provisioning info |
|
|
336
|
+
| **Enforcement** | `required`, `tags` | Filtering, grouping, and policy |
|
|
337
|
+
|
|
338
|
+
### Agent Identity
|
|
339
|
+
|
|
340
|
+
The optional `[agent]` section identifies the AI agent:
|
|
341
|
+
|
|
342
|
+
```toml
|
|
343
|
+
[agent]
|
|
344
|
+
name = "data-pipeline-agent"
|
|
345
|
+
consumer = "agent" # agent | service | developer | ci
|
|
346
|
+
description = "ETL pipeline processor"
|
|
347
|
+
capabilities = ["read-s3", "write-postgres"]
|
|
348
|
+
expires = "2027-01-01"
|
|
349
|
+
services = ["aws", "postgres"]
|
|
350
|
+
secrets = ["DATABASE_URL", "AWS_KEY"] # When using a catalog
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Lifecycle Policy
|
|
354
|
+
|
|
355
|
+
The optional `[lifecycle]` section configures audit behavior:
|
|
356
|
+
|
|
357
|
+
```toml
|
|
358
|
+
[lifecycle]
|
|
359
|
+
stale_warning_days = 90 # Flag secrets older than N days without updates
|
|
360
|
+
require_expiration = true # Require expires on all secrets
|
|
361
|
+
require_service = true # Require service on all secrets
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Library API
|
|
365
|
+
|
|
366
|
+
envpkt is also available as a TypeScript library with a functional programming API built on [functype](https://github.com/jordanburke/functype). All functions return `Either<Error, Result>` or `Option<T>` — no thrown exceptions.
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { boot, bootSafe, loadConfig, computeAudit, scanFleet, resolveConfig } from "envpkt"
|
|
370
|
+
|
|
371
|
+
// Boot API — load config, resolve catalog, audit, inject secrets
|
|
372
|
+
const result = boot({ configPath: "envpkt.toml", inject: true })
|
|
373
|
+
console.log(result.audit.status) // "healthy" | "degraded" | "critical"
|
|
374
|
+
|
|
375
|
+
// Safe variant returns Either instead of throwing
|
|
376
|
+
const safe = bootSafe({ configPath: "envpkt.toml" })
|
|
377
|
+
safe.fold(
|
|
378
|
+
(err) => console.error("Boot failed:", err._tag),
|
|
379
|
+
(result) => console.log(`${result.injected.length} secrets injected`),
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
// Load and audit directly
|
|
383
|
+
const config = loadConfig("envpkt.toml")
|
|
384
|
+
config.fold(
|
|
385
|
+
(err) => console.error("Failed:", err._tag),
|
|
386
|
+
(config) => {
|
|
387
|
+
const audit = computeAudit(config)
|
|
388
|
+
audit.secrets.forEach((s) => {
|
|
389
|
+
s.days_remaining.fold(
|
|
390
|
+
() => console.log(`${s.key}: no expiration set`),
|
|
391
|
+
(days) => console.log(`${s.key}: ${days} days remaining`),
|
|
392
|
+
)
|
|
393
|
+
})
|
|
394
|
+
},
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
// Fleet scan
|
|
398
|
+
const fleet = scanFleet("/opt/agents", { maxDepth: 3 })
|
|
399
|
+
console.log(`${fleet.total_agents} agents, ${fleet.total_secrets} secrets`)
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Packet Formatting API
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
import { formatPacket, maskValue } from "envpkt"
|
|
406
|
+
|
|
407
|
+
// formatPacket produces a human-readable text summary of a resolved config
|
|
408
|
+
const text = formatPacket(resolveResult)
|
|
409
|
+
|
|
410
|
+
// With secret values (masked by default)
|
|
411
|
+
const masked = formatPacket(resolveResult, {
|
|
412
|
+
secrets: { DATABASE_URL: "postgres://user:pass@host/db" },
|
|
413
|
+
})
|
|
414
|
+
// DATABASE_URL → postgres = pos•••••t/db
|
|
415
|
+
|
|
416
|
+
// With plaintext secret values
|
|
417
|
+
const plain = formatPacket(resolveResult, {
|
|
418
|
+
secrets: { DATABASE_URL: "postgres://user:pass@host/db" },
|
|
419
|
+
secretDisplay: "plaintext",
|
|
420
|
+
})
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Environment Scan/Check API
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { envScan, envCheck, generateTomlFromScan, matchEnvVar } from "envpkt"
|
|
427
|
+
|
|
428
|
+
// Scan process.env for credentials
|
|
429
|
+
const scan = envScan(process.env)
|
|
430
|
+
console.log(`Found ${scan.discovered.size} credentials (${scan.high_confidence} high confidence)`)
|
|
431
|
+
|
|
432
|
+
scan.discovered.forEach((m) => {
|
|
433
|
+
const svc = m.service.fold(
|
|
434
|
+
() => "unknown",
|
|
435
|
+
(s) => s,
|
|
436
|
+
)
|
|
437
|
+
console.log(` ${m.envVar} → ${svc} (${m.confidence})`)
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
// Generate TOML blocks from scan results
|
|
441
|
+
const toml = generateTomlFromScan(scan.discovered.toArray())
|
|
442
|
+
|
|
443
|
+
// Check drift between config and live env
|
|
444
|
+
import { loadConfig } from "envpkt"
|
|
445
|
+
|
|
446
|
+
loadConfig("envpkt.toml").fold(
|
|
447
|
+
(err) => console.error(err),
|
|
448
|
+
(config) => {
|
|
449
|
+
const check = envCheck(config, process.env)
|
|
450
|
+
if (!check.is_clean) {
|
|
451
|
+
console.log(`${check.missing_from_env} missing, ${check.untracked_credentials} untracked`)
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
// Match a single env var
|
|
457
|
+
matchEnvVar("OPENAI_API_KEY", "sk-test123").fold(
|
|
458
|
+
() => console.log("Not a credential"),
|
|
459
|
+
(m) => console.log(`Matched: ${m.confidence} confidence`),
|
|
460
|
+
)
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Catalog Resolution API
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
import { loadConfig, resolveConfig } from "envpkt"
|
|
467
|
+
import { dirname } from "node:path"
|
|
468
|
+
|
|
469
|
+
const configPath = "agents/pipeline/envpkt.toml"
|
|
470
|
+
loadConfig(configPath).fold(
|
|
471
|
+
(err) => console.error(err),
|
|
472
|
+
(config) => {
|
|
473
|
+
resolveConfig(config, dirname(configPath)).fold(
|
|
474
|
+
(err) => console.error("Catalog error:", err._tag),
|
|
475
|
+
(result) => {
|
|
476
|
+
console.log("Resolved keys:", result.merged)
|
|
477
|
+
console.log("Overridden:", result.overridden)
|
|
478
|
+
// result.config is the flat, self-contained config
|
|
479
|
+
},
|
|
480
|
+
)
|
|
481
|
+
},
|
|
482
|
+
)
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## fnox Integration
|
|
486
|
+
|
|
487
|
+
envpkt integrates with [fnox](https://github.com/jordanburke/fnox) for secret resolution:
|
|
488
|
+
|
|
489
|
+
- `envpkt init --from-fnox` scaffolds `[meta.*]` entries from `fnox.toml`
|
|
490
|
+
- `envpkt audit` detects orphaned keys (in envpkt but not in fnox, or vice versa)
|
|
491
|
+
- `envpkt exec` injects fnox secrets into the subprocess environment
|
|
492
|
+
|
|
493
|
+
## Development
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
pnpm install
|
|
497
|
+
pnpm validate # format + lint + typecheck + test + build:schema + build
|
|
498
|
+
pnpm test # Run tests only
|
|
499
|
+
pnpm dev # Watch mode
|
|
500
|
+
pnpm demo # Regenerate demo HTML renders in examples/demo/
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
See [`examples/demo/`](./examples/demo/) for a walkthrough of the catalog system with 3 agents, including styled HTML renders of the inspect output in all 3 display modes (no secrets, masked, plaintext).
|
|
504
|
+
|
|
505
|
+
## License
|
|
506
|
+
|
|
507
|
+
Apache-2.0
|