envpkt 0.8.0 → 0.8.1
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/dist/cli.js +20 -10
- package/dist/index.d.ts +1 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -825,14 +825,14 @@ const extractFnoxKeys = (config) => new Set(Object.keys(config.secrets));
|
|
|
825
825
|
//#region src/core/keygen.ts
|
|
826
826
|
/** Resolve the age identity file path: ENVPKT_AGE_KEY_FILE env var > ~/.envpkt/age-key.txt */
|
|
827
827
|
const resolveKeyPath = () => process.env["ENVPKT_AGE_KEY_FILE"] ?? join(homedir(), ".envpkt", "age-key.txt");
|
|
828
|
-
/** Generate an age keypair and write to disk */
|
|
828
|
+
/** Generate an age keypair and write to disk. Refuses to overwrite if the file already exists. */
|
|
829
829
|
const generateKeypair = (options) => {
|
|
830
830
|
if (!ageAvailable()) return Left({
|
|
831
831
|
_tag: "AgeNotFound",
|
|
832
832
|
message: "age-keygen CLI not found on PATH. Install age: https://github.com/FiloSottile/age"
|
|
833
833
|
});
|
|
834
834
|
const outputPath = options?.outputPath ?? resolveKeyPath();
|
|
835
|
-
if (existsSync(outputPath)
|
|
835
|
+
if (existsSync(outputPath)) return Left({
|
|
836
836
|
_tag: "KeyExists",
|
|
837
837
|
path: outputPath
|
|
838
838
|
});
|
|
@@ -2738,15 +2738,26 @@ const tildeShorten = (p) => {
|
|
|
2738
2738
|
};
|
|
2739
2739
|
/** Derive a default identity name from the config path's parent directory */
|
|
2740
2740
|
const deriveIdentityName = (configPath) => basename(dirname(resolve(configPath)));
|
|
2741
|
+
/**
|
|
2742
|
+
* Derive a project-specific key path from the config path.
|
|
2743
|
+
* - `envpkt.toml` → `~/.envpkt/<dir>-key.txt`
|
|
2744
|
+
* - `prod.envpkt.toml` → `~/.envpkt/<dir>-prod-key.txt`
|
|
2745
|
+
* - `foo.envpkt.toml` → `~/.envpkt/<dir>-foo-key.txt`
|
|
2746
|
+
*/
|
|
2747
|
+
const deriveKeyPath = (configPath) => {
|
|
2748
|
+
const abs = resolve(configPath);
|
|
2749
|
+
const dir = basename(dirname(abs));
|
|
2750
|
+
const stem = basename(abs).replace(/\.envpkt\.toml$/, "").replace(/\.toml$/, "");
|
|
2751
|
+
const name = stem === "envpkt" || stem === "" ? dir : `${dir}-${stem}`;
|
|
2752
|
+
return join(homedir(), ".envpkt", `${name}-key.txt`);
|
|
2753
|
+
};
|
|
2741
2754
|
const runKeygen = (options) => {
|
|
2742
|
-
const
|
|
2743
|
-
generateKeypair({
|
|
2744
|
-
force: options.force,
|
|
2745
|
-
outputPath
|
|
2746
|
-
}).fold((err) => {
|
|
2755
|
+
const configPath = resolve(options.config ?? join(process.cwd(), "envpkt.toml"));
|
|
2756
|
+
generateKeypair({ outputPath: options.output ?? (options.global ? resolveKeyPath() : deriveKeyPath(configPath)) }).fold((err) => {
|
|
2747
2757
|
if (err._tag === "KeyExists") {
|
|
2748
2758
|
console.error(`${YELLOW}Warning:${RESET} Identity file already exists: ${CYAN}${err.path}${RESET}`);
|
|
2749
|
-
console.error(`${DIM}
|
|
2759
|
+
console.error(`${DIM}To replace it: remove the file first, then re-run keygen.${RESET}`);
|
|
2760
|
+
console.error(`${DIM}To use a different path: pass -o <path>.${RESET}`);
|
|
2750
2761
|
process.exit(1);
|
|
2751
2762
|
}
|
|
2752
2763
|
console.error(formatError(err));
|
|
@@ -2755,7 +2766,6 @@ const runKeygen = (options) => {
|
|
|
2755
2766
|
console.log(`${GREEN}Generated${RESET} age identity: ${CYAN}${identityPath}${RESET}`);
|
|
2756
2767
|
console.log(`${BOLD}Recipient:${RESET} ${recipient}`);
|
|
2757
2768
|
console.log("");
|
|
2758
|
-
const configPath = resolve(options.config ?? join(process.cwd(), "envpkt.toml"));
|
|
2759
2769
|
if (existsSync(configPath)) {
|
|
2760
2770
|
const name = deriveIdentityName(configPath);
|
|
2761
2771
|
const keyFile = tildeShorten(identityPath);
|
|
@@ -3661,7 +3671,7 @@ program.name("envpkt").description("Credential lifecycle and fleet management fo
|
|
|
3661
3671
|
program.command("init").description("Initialize a new envpkt.toml in the current directory").option("--from-fnox [path]", "Scaffold from fnox.toml (optionally specify path)").option("--catalog <path>", "Path to shared secret catalog").option("--identity", "Include [identity] section").option("--name <name>", "Identity name (requires --identity)").option("--capabilities <caps>", "Comma-separated capabilities (requires --identity)").option("--expires <date>", "Credential expiration YYYY-MM-DD (requires --identity)").option("--force", "Overwrite existing envpkt.toml").action((options) => {
|
|
3662
3672
|
runInit(process.cwd(), options);
|
|
3663
3673
|
});
|
|
3664
|
-
program.command("keygen").description("Generate an age keypair for sealing secrets — run this before `seal` if you don't have a key yet").option("-c, --config <path>", "Path to envpkt.toml (updates identity.recipient if found)").option("
|
|
3674
|
+
program.command("keygen").description("Generate an age keypair for sealing secrets — run this before `seal` if you don't have a key yet").option("-c, --config <path>", "Path to envpkt.toml (updates identity.recipient if found)").option("-o, --output <path>", "Output path for identity file (default: ~/.envpkt/<project>-key.txt)").option("--global", "Write key to the shared default path (~/.envpkt/age-key.txt) instead of a project-specific one").action((options) => {
|
|
3665
3675
|
runKeygen(options);
|
|
3666
3676
|
});
|
|
3667
3677
|
program.command("audit").description("Audit credential health from envpkt.toml (use --strict in CI pipelines to gate deploys)").option("-c, --config <path>", "Path to envpkt.toml").option("--format <format>", "Output format: table | json | minimal", "table").option("--expiring <days>", "Show secrets expiring within N days", parseInt).option("--status <status>", "Filter by status: healthy | expiring_soon | expired | stale | missing").option("--strict", "Exit non-zero on any non-healthy secret").option("--all", "Show both secrets and env defaults").option("--env-only", "Show only env defaults (drift detection)").option("--sealed", "Show only secrets with encrypted_value").option("--external", "Show only secrets without encrypted_value").action((options) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -453,9 +453,8 @@ declare const unsealSecrets: (meta: Readonly<Record<string, SecretMeta>>, identi
|
|
|
453
453
|
declare const resolveKeyPath: () => string;
|
|
454
454
|
/** Resolve an inline age key from ENVPKT_AGE_KEY env var (for CI) */
|
|
455
455
|
declare const resolveInlineKey: () => Option<string>;
|
|
456
|
-
/** Generate an age keypair and write to disk */
|
|
456
|
+
/** Generate an age keypair and write to disk. Refuses to overwrite if the file already exists. */
|
|
457
457
|
declare const generateKeypair: (options?: {
|
|
458
|
-
readonly force?: boolean;
|
|
459
458
|
readonly outputPath?: string;
|
|
460
459
|
}) => Either<KeygenError, KeygenResult>;
|
|
461
460
|
type UpdateIdentityOptions = {
|
package/dist/index.js
CHANGED
|
@@ -1429,14 +1429,14 @@ const resolveInlineKey = () => {
|
|
|
1429
1429
|
const key = process.env["ENVPKT_AGE_KEY"];
|
|
1430
1430
|
return key ? Some(key) : None();
|
|
1431
1431
|
};
|
|
1432
|
-
/** Generate an age keypair and write to disk */
|
|
1432
|
+
/** Generate an age keypair and write to disk. Refuses to overwrite if the file already exists. */
|
|
1433
1433
|
const generateKeypair = (options) => {
|
|
1434
1434
|
if (!ageAvailable()) return Left({
|
|
1435
1435
|
_tag: "AgeNotFound",
|
|
1436
1436
|
message: "age-keygen CLI not found on PATH. Install age: https://github.com/FiloSottile/age"
|
|
1437
1437
|
});
|
|
1438
1438
|
const outputPath = options?.outputPath ?? resolveKeyPath();
|
|
1439
|
-
if (existsSync(outputPath)
|
|
1439
|
+
if (existsSync(outputPath)) return Left({
|
|
1440
1440
|
_tag: "KeyExists",
|
|
1441
1441
|
path: outputPath
|
|
1442
1442
|
});
|