envpkt 0.11.9 → 0.12.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/dist/cli.js +144 -43
- package/dist/index.js +60 -16
- package/package.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { appendFileSync, chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { Command } from "commander";
|
|
6
|
-
import { $, Cond, Do, Either, Left, List, Map as Map$1, Option, Right, Set as Set$1, Try } from "functype";
|
|
6
|
+
import { $, Cond, Do, Either, Left, List, Map as Map$1, None, Option, Right, Set as Set$1, Some, Try } from "functype";
|
|
7
7
|
import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
8
8
|
import { Env, Fs, Path, Platform } from "functype-os";
|
|
9
9
|
import { TomlDate, parse, stringify } from "smol-toml";
|
|
10
10
|
import { FormatRegistry, Type } from "@sinclair/typebox";
|
|
11
|
+
import { randomBytes } from "node:crypto";
|
|
12
|
+
import { homedir, tmpdir } from "node:os";
|
|
11
13
|
import { directSilentLogger } from "functype-log/direct";
|
|
12
14
|
import { execFileSync } from "node:child_process";
|
|
13
|
-
import { homedir } from "node:os";
|
|
14
15
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
15
16
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
16
17
|
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -1062,6 +1063,11 @@ const formatAliasError = (error) => {
|
|
|
1062
1063
|
//#region src/core/keygen.ts
|
|
1063
1064
|
/** Resolve the age identity file path: ENVPKT_AGE_KEY_FILE env var > ~/.envpkt/age-key.txt */
|
|
1064
1065
|
const resolveKeyPath = () => process.env["ENVPKT_AGE_KEY_FILE"] ?? join(homedir(), ".envpkt", "age-key.txt");
|
|
1066
|
+
/** Resolve an inline age key from ENVPKT_AGE_KEY env var (for CI) */
|
|
1067
|
+
const resolveInlineKey = () => {
|
|
1068
|
+
const key = process.env["ENVPKT_AGE_KEY"];
|
|
1069
|
+
return key ? Some(key) : None();
|
|
1070
|
+
};
|
|
1065
1071
|
/** Generate an age keypair and write to disk. Refuses to overwrite if the file already exists. */
|
|
1066
1072
|
const generateKeypair = (options) => {
|
|
1067
1073
|
if (!ageAvailable()) return Left({
|
|
@@ -1297,6 +1303,47 @@ const resolveIdentityFilePath = (config, configDir, useDefaultFallback) => {
|
|
|
1297
1303
|
const defaultPath = resolveKeyPath();
|
|
1298
1304
|
return existsSync(defaultPath) ? Option(defaultPath) : Option(void 0);
|
|
1299
1305
|
};
|
|
1306
|
+
const noop = () => {};
|
|
1307
|
+
/** Write an inline age key to a private temp file so the `age` CLI (file-based) can use it. */
|
|
1308
|
+
const materializeInlineKey = (key) => {
|
|
1309
|
+
const dir = mkdtempSync(join(tmpdir(), "envpkt-age-"));
|
|
1310
|
+
const keyPath = join(dir, "age-key.txt");
|
|
1311
|
+
writeFileSync(keyPath, key.endsWith("\n") ? key : `${key}\n`);
|
|
1312
|
+
chmodSync(keyPath, 384);
|
|
1313
|
+
return {
|
|
1314
|
+
path: keyPath,
|
|
1315
|
+
dispose: () => rmSync(dir, {
|
|
1316
|
+
recursive: true,
|
|
1317
|
+
force: true
|
|
1318
|
+
})
|
|
1319
|
+
};
|
|
1320
|
+
};
|
|
1321
|
+
/**
|
|
1322
|
+
* Resolve an age identity for unsealing sealed packets. Precedence:
|
|
1323
|
+
* config.identity.key_file > ENVPKT_AGE_KEY_FILE > ENVPKT_AGE_KEY (inline) > ~/.envpkt/age-key.txt
|
|
1324
|
+
* The inline key (CI secret) ranks above the homedir default so an explicit
|
|
1325
|
+
* env var beats a stray local key. Inline keys are written to a 0600 temp file
|
|
1326
|
+
* the caller must dispose().
|
|
1327
|
+
*/
|
|
1328
|
+
const resolveSealIdentity = (config, configDir) => {
|
|
1329
|
+
if (config.identity?.key_file) return Option({
|
|
1330
|
+
path: resolve(configDir, expandPath(config.identity.key_file)),
|
|
1331
|
+
dispose: noop
|
|
1332
|
+
});
|
|
1333
|
+
const envFile = process.env["ENVPKT_AGE_KEY_FILE"];
|
|
1334
|
+
if (envFile && existsSync(envFile)) return Option({
|
|
1335
|
+
path: envFile,
|
|
1336
|
+
dispose: noop
|
|
1337
|
+
});
|
|
1338
|
+
const inlineKey = resolveInlineKey().orUndefined();
|
|
1339
|
+
if (inlineKey) return Option(materializeInlineKey(inlineKey));
|
|
1340
|
+
const defaultPath = join(homedir(), ".envpkt", "age-key.txt");
|
|
1341
|
+
if (existsSync(defaultPath)) return Option({
|
|
1342
|
+
path: defaultPath,
|
|
1343
|
+
dispose: noop
|
|
1344
|
+
});
|
|
1345
|
+
return Option(void 0);
|
|
1346
|
+
};
|
|
1300
1347
|
const resolveIdentityKey = (config, configDir) => {
|
|
1301
1348
|
return resolveIdentityFilePath(config, configDir, false).fold(() => Right(Option(void 0)), (path) => unwrapAgentKey(path).fold((err) => Left(err), (key) => Right(Option(key))));
|
|
1302
1349
|
};
|
|
@@ -1379,23 +1426,26 @@ const bootSafe = (options) => {
|
|
|
1379
1426
|
process.env[envEnv(key)] = value;
|
|
1380
1427
|
});
|
|
1381
1428
|
const sealedKeys = /* @__PURE__ */ new Set();
|
|
1382
|
-
|
|
1383
|
-
if (hasSealedValues) identityFilePath.fold(() => {
|
|
1429
|
+
if (hasSealedValues) resolveSealIdentity(config, configDir).fold(() => {
|
|
1384
1430
|
log.warn("phase.sealed.no_identity_file", { sealed_keys: nonAliasMetaKeys.filter((k) => !!nonAliasSecretEntries[k]?.encrypted_value).length });
|
|
1385
1431
|
warnings.push("Sealed values found but no identity file available for decryption");
|
|
1386
|
-
}, (idPath) => {
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1432
|
+
}, ({ path: idPath, dispose }) => {
|
|
1433
|
+
try {
|
|
1434
|
+
unsealSecrets(nonAliasSecretEntries, idPath).fold((err) => {
|
|
1435
|
+
log.warn("phase.sealed.decrypt_failed", { message: err.message });
|
|
1436
|
+
warnings.push(`Sealed value decryption failed: ${err.message}`);
|
|
1437
|
+
}, (unsealed) => {
|
|
1438
|
+
const unsealedEntries = Object.entries(unsealed);
|
|
1439
|
+
Object.assign(secrets, unsealed);
|
|
1440
|
+
injected.push(...unsealedEntries.map(([key]) => key));
|
|
1441
|
+
unsealedEntries.forEach(([key]) => {
|
|
1442
|
+
sealedKeys.add(key);
|
|
1443
|
+
log.debug("phase.sealed.resolved", { key });
|
|
1444
|
+
});
|
|
1397
1445
|
});
|
|
1398
|
-
}
|
|
1446
|
+
} finally {
|
|
1447
|
+
dispose();
|
|
1448
|
+
}
|
|
1399
1449
|
});
|
|
1400
1450
|
const remainingKeys = nonAliasMetaKeys.filter((k) => !sealedKeys.has(k));
|
|
1401
1451
|
if (remainingKeys.length > 0) if (fnoxAvailable()) fnoxExport(opts.profile, identityKey.orUndefined()).fold((err) => {
|
|
@@ -2693,38 +2743,86 @@ const runEnvCheck = (options) => {
|
|
|
2693
2743
|
});
|
|
2694
2744
|
};
|
|
2695
2745
|
const shellEscape = (value) => value.replace(/'/g, "'\\''");
|
|
2746
|
+
/** Shared resolution for the emit commands (`export`, `github`): resolve without injecting. */
|
|
2747
|
+
const resolveForEmit = (options) => bootSafe({
|
|
2748
|
+
inject: false,
|
|
2749
|
+
configPath: options.config,
|
|
2750
|
+
profile: options.profile,
|
|
2751
|
+
warnOnly: true
|
|
2752
|
+
});
|
|
2753
|
+
/**
|
|
2754
|
+
* Flatten a resolved BootResult into the ordered (wire-name, value) pairs to emit:
|
|
2755
|
+
* env defaults, then overridden env entries (value from config), then secrets (which
|
|
2756
|
+
* override). `secret` marks values that consumers must redact (e.g. GitHub masking).
|
|
2757
|
+
*/
|
|
2758
|
+
const collectEmitEntries = (boot) => {
|
|
2759
|
+
const wireName = (key) => boot.envNames[key] ?? key;
|
|
2760
|
+
const defaults = Object.entries(boot.envDefaults).map(([key, value]) => ({
|
|
2761
|
+
name: wireName(key),
|
|
2762
|
+
value,
|
|
2763
|
+
secret: false
|
|
2764
|
+
}));
|
|
2765
|
+
const overridden = boot.overridden.length === 0 ? [] : loadConfig(boot.configPath).fold(() => [], (config) => {
|
|
2766
|
+
const envEntries = config.env ?? {};
|
|
2767
|
+
return boot.overridden.flatMap((key) => {
|
|
2768
|
+
const entry = envEntries[key];
|
|
2769
|
+
if (!entry) return [];
|
|
2770
|
+
const name = wireName(key);
|
|
2771
|
+
return [{
|
|
2772
|
+
name,
|
|
2773
|
+
value: entry.value ?? process.env[name] ?? "",
|
|
2774
|
+
secret: false
|
|
2775
|
+
}];
|
|
2776
|
+
});
|
|
2777
|
+
});
|
|
2778
|
+
const secrets = Object.entries(boot.secrets).map(([key, value]) => ({
|
|
2779
|
+
name: wireName(key),
|
|
2780
|
+
value,
|
|
2781
|
+
secret: true
|
|
2782
|
+
}));
|
|
2783
|
+
return [
|
|
2784
|
+
...defaults,
|
|
2785
|
+
...overridden,
|
|
2786
|
+
...secrets
|
|
2787
|
+
];
|
|
2788
|
+
};
|
|
2789
|
+
const emitWarnings = (boot) => {
|
|
2790
|
+
const sourceMsg = formatConfigSource(boot.configPath, boot.configSource);
|
|
2791
|
+
if (sourceMsg) console.error(sourceMsg);
|
|
2792
|
+
boot.warnings.forEach((warning) => {
|
|
2793
|
+
console.error(`${YELLOW}Warning:${RESET} ${warning}`);
|
|
2794
|
+
});
|
|
2795
|
+
};
|
|
2696
2796
|
const runEnvExport = (options) => {
|
|
2697
|
-
|
|
2698
|
-
inject: false,
|
|
2699
|
-
configPath: options.config,
|
|
2700
|
-
profile: options.profile,
|
|
2701
|
-
warnOnly: true
|
|
2702
|
-
}).fold((err) => {
|
|
2797
|
+
resolveForEmit(options).fold((err) => {
|
|
2703
2798
|
console.error(formatError(err));
|
|
2704
2799
|
process.exit(2);
|
|
2705
2800
|
}, (boot) => {
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
console.error(`${YELLOW}Warning:${RESET} ${warning}`);
|
|
2710
|
-
});
|
|
2711
|
-
const wireName = (key) => boot.envNames[key] ?? key;
|
|
2712
|
-
Object.entries(boot.envDefaults).forEach(([key, value]) => {
|
|
2713
|
-
console.log(`export ${wireName(key)}='${shellEscape(value)}'`);
|
|
2714
|
-
});
|
|
2715
|
-
if (boot.overridden.length > 0) loadConfig(boot.configPath).fold(() => {}, (config) => {
|
|
2716
|
-
const envEntries = config.env ?? {};
|
|
2717
|
-
boot.overridden.forEach((key) => {
|
|
2718
|
-
if (!(key in envEntries)) return;
|
|
2719
|
-
const entry = envEntries[key];
|
|
2720
|
-
const name = wireName(key);
|
|
2721
|
-
const value = entry.value ?? process.env[name] ?? "";
|
|
2722
|
-
console.log(`export ${name}='${shellEscape(value)}'`);
|
|
2723
|
-
});
|
|
2801
|
+
emitWarnings(boot);
|
|
2802
|
+
collectEmitEntries(boot).forEach(({ name, value }) => {
|
|
2803
|
+
console.log(`export ${name}='${shellEscape(value)}'`);
|
|
2724
2804
|
});
|
|
2725
|
-
|
|
2726
|
-
|
|
2805
|
+
});
|
|
2806
|
+
};
|
|
2807
|
+
const runEnvGithub = (options) => {
|
|
2808
|
+
resolveForEmit(options).fold((err) => {
|
|
2809
|
+
console.error(formatError(err));
|
|
2810
|
+
process.exit(2);
|
|
2811
|
+
}, (boot) => {
|
|
2812
|
+
emitWarnings(boot);
|
|
2813
|
+
const entries = collectEmitEntries(boot);
|
|
2814
|
+
entries.filter((e) => e.secret).forEach((e) => console.log(`::add-mask::${e.value}`));
|
|
2815
|
+
const lines = entries.map(({ name, value }) => {
|
|
2816
|
+
const delim = `__ENVPKT_${randomBytes(9).toString("hex")}__`;
|
|
2817
|
+
return `${name}<<${delim}\n${value}\n${delim}`;
|
|
2727
2818
|
});
|
|
2819
|
+
const githubEnv = process.env["GITHUB_ENV"];
|
|
2820
|
+
if (githubEnv) appendFileSync(githubEnv, lines.length > 0 ? `${lines.join("\n")}\n` : "");
|
|
2821
|
+
else {
|
|
2822
|
+
console.error(`${YELLOW}Warning:${RESET} GITHUB_ENV not set — printing assignments to stdout (not a GitHub Actions runner)`);
|
|
2823
|
+
lines.forEach((l) => console.log(l));
|
|
2824
|
+
}
|
|
2825
|
+
if (options.strict) process.exit(exitCodeForAudit(boot.audit));
|
|
2728
2826
|
});
|
|
2729
2827
|
};
|
|
2730
2828
|
const buildEnvBlock = (name, value, options) => {
|
|
@@ -2922,6 +3020,9 @@ const registerEnvCommands = (program) => {
|
|
|
2922
3020
|
env.command("export").description("Output export statements for eval-ing secrets into the current shell. Usage: eval \"$(envpkt env export)\"").option("-c, --config <path>", "Path to envpkt.toml").option("--profile <profile>", "fnox profile to use").option("--skip-audit", "Skip the pre-flight audit").action((options) => {
|
|
2923
3021
|
runEnvExport(options);
|
|
2924
3022
|
});
|
|
3023
|
+
env.command("github").description("Inject resolved secrets into $GITHUB_ENV for GitHub Actions, masking secret values in the log (::add-mask::)").option("-c, --config <path>", "Path to envpkt.toml").option("--profile <profile>", "fnox profile to use").option("--strict", "Exit non-zero if the pre-flight audit is not healthy").action((options) => {
|
|
3024
|
+
runEnvGithub(options);
|
|
3025
|
+
});
|
|
2925
3026
|
env.command("add").description("Add a new environment default entry to envpkt.toml").argument("<name>", "Environment variable name").argument("<value>", "Default value").option("-c, --config <path>", "Path to envpkt.toml").option("--purpose <purpose>", "Why this env var exists").option("--comment <comment>", "Free-form annotation").option("--tags <tags>", "Comma-separated key=value tags (e.g. env=prod,team=payments)").option("--dry-run", "Preview the TOML block without writing").action((name, value, options) => {
|
|
2926
3027
|
runEnvAdd(name, value, options);
|
|
2927
3028
|
});
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,10 @@ import { TypeCompiler } from "@sinclair/typebox/compiler";
|
|
|
4
4
|
import { $, Cond, Do, Either, Left, List, Map as Map$1, None, Option, Right, Set as Set$1, Some, Try } from "functype";
|
|
5
5
|
import { Env, Fs, Path, Platform } from "functype-os";
|
|
6
6
|
import { TomlDate, parse } from "smol-toml";
|
|
7
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { homedir, tmpdir } from "node:os";
|
|
8
9
|
import { createDirectConsoleLogger, createDirectTestLogger, directSilentLogger, directSilentLogger as directSilentLogger$1 } from "functype-log/direct";
|
|
9
10
|
import { execFileSync } from "node:child_process";
|
|
10
|
-
import { homedir } from "node:os";
|
|
11
11
|
import { createInterface } from "node:readline";
|
|
12
12
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
13
13
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -1926,6 +1926,47 @@ const resolveIdentityFilePath = (config, configDir, useDefaultFallback) => {
|
|
|
1926
1926
|
const defaultPath = resolveKeyPath();
|
|
1927
1927
|
return existsSync(defaultPath) ? Option(defaultPath) : Option(void 0);
|
|
1928
1928
|
};
|
|
1929
|
+
const noop = () => {};
|
|
1930
|
+
/** Write an inline age key to a private temp file so the `age` CLI (file-based) can use it. */
|
|
1931
|
+
const materializeInlineKey = (key) => {
|
|
1932
|
+
const dir = mkdtempSync(join(tmpdir(), "envpkt-age-"));
|
|
1933
|
+
const keyPath = join(dir, "age-key.txt");
|
|
1934
|
+
writeFileSync(keyPath, key.endsWith("\n") ? key : `${key}\n`);
|
|
1935
|
+
chmodSync(keyPath, 384);
|
|
1936
|
+
return {
|
|
1937
|
+
path: keyPath,
|
|
1938
|
+
dispose: () => rmSync(dir, {
|
|
1939
|
+
recursive: true,
|
|
1940
|
+
force: true
|
|
1941
|
+
})
|
|
1942
|
+
};
|
|
1943
|
+
};
|
|
1944
|
+
/**
|
|
1945
|
+
* Resolve an age identity for unsealing sealed packets. Precedence:
|
|
1946
|
+
* config.identity.key_file > ENVPKT_AGE_KEY_FILE > ENVPKT_AGE_KEY (inline) > ~/.envpkt/age-key.txt
|
|
1947
|
+
* The inline key (CI secret) ranks above the homedir default so an explicit
|
|
1948
|
+
* env var beats a stray local key. Inline keys are written to a 0600 temp file
|
|
1949
|
+
* the caller must dispose().
|
|
1950
|
+
*/
|
|
1951
|
+
const resolveSealIdentity = (config, configDir) => {
|
|
1952
|
+
if (config.identity?.key_file) return Option({
|
|
1953
|
+
path: resolve(configDir, expandPath(config.identity.key_file)),
|
|
1954
|
+
dispose: noop
|
|
1955
|
+
});
|
|
1956
|
+
const envFile = process.env["ENVPKT_AGE_KEY_FILE"];
|
|
1957
|
+
if (envFile && existsSync(envFile)) return Option({
|
|
1958
|
+
path: envFile,
|
|
1959
|
+
dispose: noop
|
|
1960
|
+
});
|
|
1961
|
+
const inlineKey = resolveInlineKey().orUndefined();
|
|
1962
|
+
if (inlineKey) return Option(materializeInlineKey(inlineKey));
|
|
1963
|
+
const defaultPath = join(homedir(), ".envpkt", "age-key.txt");
|
|
1964
|
+
if (existsSync(defaultPath)) return Option({
|
|
1965
|
+
path: defaultPath,
|
|
1966
|
+
dispose: noop
|
|
1967
|
+
});
|
|
1968
|
+
return Option(void 0);
|
|
1969
|
+
};
|
|
1929
1970
|
const resolveIdentityKey = (config, configDir) => {
|
|
1930
1971
|
return resolveIdentityFilePath(config, configDir, false).fold(() => Right(Option(void 0)), (path) => unwrapAgentKey(path).fold((err) => Left(err), (key) => Right(Option(key))));
|
|
1931
1972
|
};
|
|
@@ -2008,23 +2049,26 @@ const bootSafe = (options) => {
|
|
|
2008
2049
|
process.env[envEnv(key)] = value;
|
|
2009
2050
|
});
|
|
2010
2051
|
const sealedKeys = /* @__PURE__ */ new Set();
|
|
2011
|
-
|
|
2012
|
-
if (hasSealedValues) identityFilePath.fold(() => {
|
|
2052
|
+
if (hasSealedValues) resolveSealIdentity(config, configDir).fold(() => {
|
|
2013
2053
|
log.warn("phase.sealed.no_identity_file", { sealed_keys: nonAliasMetaKeys.filter((k) => !!nonAliasSecretEntries[k]?.encrypted_value).length });
|
|
2014
2054
|
warnings.push("Sealed values found but no identity file available for decryption");
|
|
2015
|
-
}, (idPath) => {
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2055
|
+
}, ({ path: idPath, dispose }) => {
|
|
2056
|
+
try {
|
|
2057
|
+
unsealSecrets(nonAliasSecretEntries, idPath).fold((err) => {
|
|
2058
|
+
log.warn("phase.sealed.decrypt_failed", { message: err.message });
|
|
2059
|
+
warnings.push(`Sealed value decryption failed: ${err.message}`);
|
|
2060
|
+
}, (unsealed) => {
|
|
2061
|
+
const unsealedEntries = Object.entries(unsealed);
|
|
2062
|
+
Object.assign(secrets, unsealed);
|
|
2063
|
+
injected.push(...unsealedEntries.map(([key]) => key));
|
|
2064
|
+
unsealedEntries.forEach(([key]) => {
|
|
2065
|
+
sealedKeys.add(key);
|
|
2066
|
+
log.debug("phase.sealed.resolved", { key });
|
|
2067
|
+
});
|
|
2026
2068
|
});
|
|
2027
|
-
}
|
|
2069
|
+
} finally {
|
|
2070
|
+
dispose();
|
|
2071
|
+
}
|
|
2028
2072
|
});
|
|
2029
2073
|
const remainingKeys = nonAliasMetaKeys.filter((k) => !sealedKeys.has(k));
|
|
2030
2074
|
if (remainingKeys.length > 0) if (fnoxAvailable()) fnoxExport(opts.profile, identityKey.orUndefined()).fold((err) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envpkt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Credential lifecycle and fleet management for AI agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"credentials",
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
43
43
|
"@sinclair/typebox": "^0.34.49",
|
|
44
44
|
"commander": "^15.0.0",
|
|
45
|
-
"functype": "^1.3.
|
|
46
|
-
"functype-log": "^1.3.
|
|
47
|
-
"functype-os": "^1.3.
|
|
45
|
+
"functype": "^1.3.1",
|
|
46
|
+
"functype-log": "^1.3.1",
|
|
47
|
+
"functype-os": "^1.3.1",
|
|
48
48
|
"smol-toml": "^1.6.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^24.13.1",
|
|
52
|
-
"ts-builds": "^3.0.
|
|
52
|
+
"ts-builds": "^3.0.1",
|
|
53
53
|
"tsdown": "^0.22.2",
|
|
54
54
|
"tsx": "^4.22.4"
|
|
55
55
|
},
|