envpkt 0.10.2 → 0.11.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 +42 -3
- package/dist/index.d.ts +10 -1
- package/dist/index.js +43 -4
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,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 { directSilentLogger } from "functype-log/direct";
|
|
11
12
|
import { execFileSync } from "node:child_process";
|
|
12
13
|
import { homedir } from "node:os";
|
|
13
14
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -1284,7 +1285,15 @@ const bootSafe = (options) => {
|
|
|
1284
1285
|
const inject = opts.inject !== false;
|
|
1285
1286
|
const failOnExpired = opts.failOnExpired !== false;
|
|
1286
1287
|
const warnOnly = opts.warnOnly ?? false;
|
|
1287
|
-
|
|
1288
|
+
const log = (opts.logger ?? directSilentLogger).withContext({ component: "envpkt.boot" });
|
|
1289
|
+
return resolveAndLoad(opts).flatMap(({ config, configPath, configDir, configSource }) => validateAliases(config).fold((err) => {
|
|
1290
|
+
log.warn("alias.validate.failed", {
|
|
1291
|
+
tag: err._tag,
|
|
1292
|
+
key: "key" in err ? err.key : void 0
|
|
1293
|
+
});
|
|
1294
|
+
return Left(err);
|
|
1295
|
+
}, (aliasTable) => {
|
|
1296
|
+
log.debug("alias.validate.success", { aliases: aliasTable.entries.size });
|
|
1288
1297
|
const secretEntries = config.secret ?? {};
|
|
1289
1298
|
const envEntries = config.env ?? {};
|
|
1290
1299
|
const nonAliasSecretEntries = Object.fromEntries(Object.entries(secretEntries).filter(([, meta]) => meta.from_key === void 0));
|
|
@@ -1313,19 +1322,28 @@ const bootSafe = (options) => {
|
|
|
1313
1322
|
const sealedKeys = /* @__PURE__ */ new Set();
|
|
1314
1323
|
const identityFilePath = resolveIdentityFilePath(config, configDir, true);
|
|
1315
1324
|
if (hasSealedValues) identityFilePath.fold(() => {
|
|
1325
|
+
log.warn("phase.sealed.no_identity_file", { sealed_keys: nonAliasMetaKeys.filter((k) => !!nonAliasSecretEntries[k]?.encrypted_value).length });
|
|
1316
1326
|
warnings.push("Sealed values found but no identity file available for decryption");
|
|
1317
1327
|
}, (idPath) => {
|
|
1318
1328
|
unsealSecrets(nonAliasSecretEntries, idPath).fold((err) => {
|
|
1329
|
+
log.warn("phase.sealed.decrypt_failed", { message: err.message });
|
|
1319
1330
|
warnings.push(`Sealed value decryption failed: ${err.message}`);
|
|
1320
1331
|
}, (unsealed) => {
|
|
1321
1332
|
const unsealedEntries = Object.entries(unsealed);
|
|
1322
1333
|
Object.assign(secrets, unsealed);
|
|
1323
1334
|
injected.push(...unsealedEntries.map(([key]) => key));
|
|
1324
|
-
unsealedEntries.
|
|
1335
|
+
unsealedEntries.forEach(([key]) => {
|
|
1336
|
+
sealedKeys.add(key);
|
|
1337
|
+
log.debug("phase.sealed.resolved", { key });
|
|
1338
|
+
});
|
|
1325
1339
|
});
|
|
1326
1340
|
});
|
|
1327
1341
|
const remainingKeys = nonAliasMetaKeys.filter((k) => !sealedKeys.has(k));
|
|
1328
1342
|
if (remainingKeys.length > 0) if (fnoxAvailable()) fnoxExport(opts.profile, identityKey.orUndefined()).fold((err) => {
|
|
1343
|
+
log.warn("phase.fnox.export_failed", {
|
|
1344
|
+
message: err.message,
|
|
1345
|
+
skipped: remainingKeys.length
|
|
1346
|
+
});
|
|
1329
1347
|
warnings.push(`fnox export failed: ${err.message}`);
|
|
1330
1348
|
skipped.push(...remainingKeys);
|
|
1331
1349
|
}, (exported) => {
|
|
@@ -1333,11 +1351,22 @@ const bootSafe = (options) => {
|
|
|
1333
1351
|
const notFound = remainingKeys.filter((key) => !(key in exported));
|
|
1334
1352
|
found.forEach((key) => {
|
|
1335
1353
|
secrets[key] = exported[key];
|
|
1354
|
+
log.debug("phase.fnox.resolved", {
|
|
1355
|
+
key,
|
|
1356
|
+
profile: opts.profile
|
|
1357
|
+
});
|
|
1358
|
+
});
|
|
1359
|
+
notFound.forEach((key) => {
|
|
1360
|
+
log.debug("phase.fnox.not_in_export", {
|
|
1361
|
+
key,
|
|
1362
|
+
profile: opts.profile
|
|
1363
|
+
});
|
|
1336
1364
|
});
|
|
1337
1365
|
injected.push(...found);
|
|
1338
1366
|
skipped.push(...notFound);
|
|
1339
1367
|
});
|
|
1340
1368
|
else {
|
|
1369
|
+
log.debug("phase.fnox.unavailable", { skipped: remainingKeys.length });
|
|
1341
1370
|
if (!hasSealedValues) warnings.push("fnox not available — no secrets injected");
|
|
1342
1371
|
else warnings.push("fnox not available — unsealed secrets could not be resolved");
|
|
1343
1372
|
skipped.push(...remainingKeys);
|
|
@@ -1349,7 +1378,17 @@ const bootSafe = (options) => {
|
|
|
1349
1378
|
if (targetValue !== void 0) {
|
|
1350
1379
|
secrets[aliasKey] = targetValue;
|
|
1351
1380
|
injected.push(aliasKey);
|
|
1352
|
-
|
|
1381
|
+
log.debug("phase.alias.copied", {
|
|
1382
|
+
alias: aliasKey,
|
|
1383
|
+
target: entry.targetKey
|
|
1384
|
+
});
|
|
1385
|
+
} else {
|
|
1386
|
+
skipped.push(aliasKey);
|
|
1387
|
+
log.debug("phase.alias.target_unresolved", {
|
|
1388
|
+
alias: aliasKey,
|
|
1389
|
+
target: entry.targetKey
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1353
1392
|
});
|
|
1354
1393
|
aliasEnvKeys.forEach((aliasKey) => {
|
|
1355
1394
|
const entry = aliasTable.entries.get(`env.${aliasKey}`);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as _$_sinclair_typebox0 from "@sinclair/typebox";
|
|
2
2
|
import { Static } from "@sinclair/typebox";
|
|
3
3
|
import { Either, List, Option } from "functype";
|
|
4
|
+
import { DirectLogger, DirectTestLoggerHandle, createDirectConsoleLogger, createDirectTestLogger, directSilentLogger } from "functype-log/direct";
|
|
4
5
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
6
|
import { CallToolResult, ReadResourceResult, Resource } from "@modelcontextprotocol/sdk/types.js";
|
|
7
|
+
import { DirectLogger as DirectLogger$1, LogEntry, LogLevel, LogMetadata } from "functype-log";
|
|
6
8
|
|
|
7
9
|
//#region src/core/schema.d.ts
|
|
8
10
|
declare const ConsumerType: _$_sinclair_typebox0.TUnion<[_$_sinclair_typebox0.TLiteral<"agent">, _$_sinclair_typebox0.TLiteral<"service">, _$_sinclair_typebox0.TLiteral<"developer">, _$_sinclair_typebox0.TLiteral<"ci">]>;
|
|
@@ -285,6 +287,13 @@ type BootOptions = {
|
|
|
285
287
|
readonly inject?: boolean;
|
|
286
288
|
readonly failOnExpired?: boolean;
|
|
287
289
|
readonly warnOnly?: boolean;
|
|
290
|
+
/**
|
|
291
|
+
* Optional diagnostic logger. Defaults to a silent logger (zero overhead).
|
|
292
|
+
* Receives structured trace events at boot resolution decision points
|
|
293
|
+
* (alias validation, sealed phase, fnox phase, alias copy phase). Useful
|
|
294
|
+
* for debugging why a particular secret landed in skipped[] vs injected[].
|
|
295
|
+
*/
|
|
296
|
+
readonly logger?: DirectLogger$1;
|
|
288
297
|
};
|
|
289
298
|
type BootResult = {
|
|
290
299
|
readonly audit: AuditResult;
|
|
@@ -622,4 +631,4 @@ type ToolDef = {
|
|
|
622
631
|
declare const toolDefinitions: readonly ToolDef[];
|
|
623
632
|
declare const callTool: (name: string, args: Record<string, unknown>) => CallToolResult;
|
|
624
633
|
//#endregion
|
|
625
|
-
export { type AgentIdentity, AgentIdentitySchema, type AliasError, type AliasTable, type AuditResult, type BootError, type BootOptions, type BootResult, type CallbackConfig, CallbackConfigSchema, type CatalogError, type CheckResult, type ConfidenceLevel, type ConfigError, type ConfigSource, type ConsumerType, type CredentialPattern, type DriftEntry, type DriftStatus, type EnvAuditResult, type EnvDriftEntry, type EnvDriftStatus, type EnvMeta, EnvMetaSchema, EnvpktBootError, type EnvpktConfig, EnvpktConfigSchema, type FleetAgent, type FleetHealth, type FnoxConfig, type FnoxError, type FnoxSecret, type FormatPacketOptions, type HealthStatus, type Identity, type IdentityError, IdentitySchema, type KeygenError, type KeygenResult, type LifecycleConfig, LifecycleConfigSchema, type MatchResult, type ResolveOptions, type ResolveResult, type ResolvedPath, type ScanOptions, type ScanResult, type SealError, type SecretDisplay, type SecretHealth, type SecretMeta, SecretMetaSchema, type SecretStatus, type TomlEditError, type ToolsConfig, ToolsConfigSchema, ageAvailable, ageDecrypt, ageEncrypt, appendSection, boot, bootSafe, callTool, compareFnoxAndEnvpkt, computeAudit, computeEnvAudit, createServer, deriveServiceFromName, detectFnox, discoverConfig, envCheck, envScan, extractFnoxKeys, findConfigPath, fnoxAvailable, fnoxExport, fnoxGet, formatAliasError, formatPacket, generateKeypair, generateTomlFromScan, isEnvAlias, isSecretAlias, loadCatalog, loadConfig, loadConfigFromCwd, maskValue, matchEnvVar, matchValueShape, parseToml, readConfigFile, readFnoxConfig, readResource, removeSection, renameSection, resolveConfig, resolveConfigPath, resolveInlineKey, resolveKeyPath, resolveSecrets, resolveValues, resourceDefinitions, scanEnv, scanFleet, sealSecrets, startServer, toolDefinitions, unsealSecrets, unwrapAgentKey, updateConfigIdentity, updateSectionFields, validateAliases, validateConfig };
|
|
634
|
+
export { type AgentIdentity, AgentIdentitySchema, type AliasError, type AliasTable, type AuditResult, type BootError, type BootOptions, type BootResult, type CallbackConfig, CallbackConfigSchema, type CatalogError, type CheckResult, type ConfidenceLevel, type ConfigError, type ConfigSource, type ConsumerType, type CredentialPattern, type DirectLogger, type DirectTestLoggerHandle, type DriftEntry, type DriftStatus, type EnvAuditResult, type EnvDriftEntry, type EnvDriftStatus, type EnvMeta, EnvMetaSchema, EnvpktBootError, type EnvpktConfig, EnvpktConfigSchema, type FleetAgent, type FleetHealth, type FnoxConfig, type FnoxError, type FnoxSecret, type FormatPacketOptions, type HealthStatus, type Identity, type IdentityError, IdentitySchema, type KeygenError, type KeygenResult, type LifecycleConfig, LifecycleConfigSchema, type LogEntry, type LogLevel, type LogMetadata, type MatchResult, type ResolveOptions, type ResolveResult, type ResolvedPath, type ScanOptions, type ScanResult, type SealError, type SecretDisplay, type SecretHealth, type SecretMeta, SecretMetaSchema, type SecretStatus, type TomlEditError, type ToolsConfig, ToolsConfigSchema, ageAvailable, ageDecrypt, ageEncrypt, appendSection, boot, bootSafe, callTool, compareFnoxAndEnvpkt, computeAudit, computeEnvAudit, createDirectConsoleLogger, createDirectTestLogger, createServer, deriveServiceFromName, detectFnox, directSilentLogger, discoverConfig, envCheck, envScan, extractFnoxKeys, findConfigPath, fnoxAvailable, fnoxExport, fnoxGet, formatAliasError, formatPacket, generateKeypair, generateTomlFromScan, isEnvAlias, isSecretAlias, loadCatalog, loadConfig, loadConfigFromCwd, maskValue, matchEnvVar, matchValueShape, parseToml, readConfigFile, readFnoxConfig, readResource, removeSection, renameSection, resolveConfig, resolveConfigPath, resolveInlineKey, resolveKeyPath, resolveSecrets, resolveValues, resourceDefinitions, scanEnv, scanFleet, sealSecrets, startServer, toolDefinitions, unsealSecrets, unwrapAgentKey, updateConfigIdentity, updateSectionFields, validateAliases, validateConfig };
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Cond, Either, Left, List, None, Option, Right, Some, Try } from "functy
|
|
|
5
5
|
import { Env, Fs, Path, Platform } from "functype-os";
|
|
6
6
|
import { TomlDate, parse } from "smol-toml";
|
|
7
7
|
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { createDirectConsoleLogger, createDirectTestLogger, directSilentLogger, directSilentLogger as directSilentLogger$1 } from "functype-log/direct";
|
|
8
9
|
import { execFileSync } from "node:child_process";
|
|
9
10
|
import { homedir } from "node:os";
|
|
10
11
|
import { createInterface } from "node:readline";
|
|
@@ -1930,7 +1931,15 @@ const bootSafe = (options) => {
|
|
|
1930
1931
|
const inject = opts.inject !== false;
|
|
1931
1932
|
const failOnExpired = opts.failOnExpired !== false;
|
|
1932
1933
|
const warnOnly = opts.warnOnly ?? false;
|
|
1933
|
-
|
|
1934
|
+
const log = (opts.logger ?? directSilentLogger$1).withContext({ component: "envpkt.boot" });
|
|
1935
|
+
return resolveAndLoad(opts).flatMap(({ config, configPath, configDir, configSource }) => validateAliases(config).fold((err) => {
|
|
1936
|
+
log.warn("alias.validate.failed", {
|
|
1937
|
+
tag: err._tag,
|
|
1938
|
+
key: "key" in err ? err.key : void 0
|
|
1939
|
+
});
|
|
1940
|
+
return Left(err);
|
|
1941
|
+
}, (aliasTable) => {
|
|
1942
|
+
log.debug("alias.validate.success", { aliases: aliasTable.entries.size });
|
|
1934
1943
|
const secretEntries = config.secret ?? {};
|
|
1935
1944
|
const envEntries = config.env ?? {};
|
|
1936
1945
|
const nonAliasSecretEntries = Object.fromEntries(Object.entries(secretEntries).filter(([, meta]) => meta.from_key === void 0));
|
|
@@ -1959,19 +1968,28 @@ const bootSafe = (options) => {
|
|
|
1959
1968
|
const sealedKeys = /* @__PURE__ */ new Set();
|
|
1960
1969
|
const identityFilePath = resolveIdentityFilePath(config, configDir, true);
|
|
1961
1970
|
if (hasSealedValues) identityFilePath.fold(() => {
|
|
1971
|
+
log.warn("phase.sealed.no_identity_file", { sealed_keys: nonAliasMetaKeys.filter((k) => !!nonAliasSecretEntries[k]?.encrypted_value).length });
|
|
1962
1972
|
warnings.push("Sealed values found but no identity file available for decryption");
|
|
1963
1973
|
}, (idPath) => {
|
|
1964
1974
|
unsealSecrets(nonAliasSecretEntries, idPath).fold((err) => {
|
|
1975
|
+
log.warn("phase.sealed.decrypt_failed", { message: err.message });
|
|
1965
1976
|
warnings.push(`Sealed value decryption failed: ${err.message}`);
|
|
1966
1977
|
}, (unsealed) => {
|
|
1967
1978
|
const unsealedEntries = Object.entries(unsealed);
|
|
1968
1979
|
Object.assign(secrets, unsealed);
|
|
1969
1980
|
injected.push(...unsealedEntries.map(([key]) => key));
|
|
1970
|
-
unsealedEntries.
|
|
1981
|
+
unsealedEntries.forEach(([key]) => {
|
|
1982
|
+
sealedKeys.add(key);
|
|
1983
|
+
log.debug("phase.sealed.resolved", { key });
|
|
1984
|
+
});
|
|
1971
1985
|
});
|
|
1972
1986
|
});
|
|
1973
1987
|
const remainingKeys = nonAliasMetaKeys.filter((k) => !sealedKeys.has(k));
|
|
1974
1988
|
if (remainingKeys.length > 0) if (fnoxAvailable()) fnoxExport(opts.profile, identityKey.orUndefined()).fold((err) => {
|
|
1989
|
+
log.warn("phase.fnox.export_failed", {
|
|
1990
|
+
message: err.message,
|
|
1991
|
+
skipped: remainingKeys.length
|
|
1992
|
+
});
|
|
1975
1993
|
warnings.push(`fnox export failed: ${err.message}`);
|
|
1976
1994
|
skipped.push(...remainingKeys);
|
|
1977
1995
|
}, (exported) => {
|
|
@@ -1979,11 +1997,22 @@ const bootSafe = (options) => {
|
|
|
1979
1997
|
const notFound = remainingKeys.filter((key) => !(key in exported));
|
|
1980
1998
|
found.forEach((key) => {
|
|
1981
1999
|
secrets[key] = exported[key];
|
|
2000
|
+
log.debug("phase.fnox.resolved", {
|
|
2001
|
+
key,
|
|
2002
|
+
profile: opts.profile
|
|
2003
|
+
});
|
|
2004
|
+
});
|
|
2005
|
+
notFound.forEach((key) => {
|
|
2006
|
+
log.debug("phase.fnox.not_in_export", {
|
|
2007
|
+
key,
|
|
2008
|
+
profile: opts.profile
|
|
2009
|
+
});
|
|
1982
2010
|
});
|
|
1983
2011
|
injected.push(...found);
|
|
1984
2012
|
skipped.push(...notFound);
|
|
1985
2013
|
});
|
|
1986
2014
|
else {
|
|
2015
|
+
log.debug("phase.fnox.unavailable", { skipped: remainingKeys.length });
|
|
1987
2016
|
if (!hasSealedValues) warnings.push("fnox not available — no secrets injected");
|
|
1988
2017
|
else warnings.push("fnox not available — unsealed secrets could not be resolved");
|
|
1989
2018
|
skipped.push(...remainingKeys);
|
|
@@ -1995,7 +2024,17 @@ const bootSafe = (options) => {
|
|
|
1995
2024
|
if (targetValue !== void 0) {
|
|
1996
2025
|
secrets[aliasKey] = targetValue;
|
|
1997
2026
|
injected.push(aliasKey);
|
|
1998
|
-
|
|
2027
|
+
log.debug("phase.alias.copied", {
|
|
2028
|
+
alias: aliasKey,
|
|
2029
|
+
target: entry.targetKey
|
|
2030
|
+
});
|
|
2031
|
+
} else {
|
|
2032
|
+
skipped.push(aliasKey);
|
|
2033
|
+
log.debug("phase.alias.target_unresolved", {
|
|
2034
|
+
alias: aliasKey,
|
|
2035
|
+
target: entry.targetKey
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
1999
2038
|
});
|
|
2000
2039
|
aliasEnvKeys.forEach((aliasKey) => {
|
|
2001
2040
|
const entry = aliasTable.entries.get(`env.${aliasKey}`);
|
|
@@ -2640,4 +2679,4 @@ const startServer = async () => {
|
|
|
2640
2679
|
await server.connect(transport);
|
|
2641
2680
|
};
|
|
2642
2681
|
//#endregion
|
|
2643
|
-
export { AgentIdentitySchema, CallbackConfigSchema, ConsumerType, EnvMetaSchema, EnvpktBootError, EnvpktConfigSchema, IdentitySchema, LifecycleConfigSchema, SecretMetaSchema, ToolsConfigSchema, ageAvailable, ageDecrypt, ageEncrypt, appendSection, boot, bootSafe, callTool, compareFnoxAndEnvpkt, computeAudit, computeEnvAudit, createServer, deriveServiceFromName, detectFnox, discoverConfig, envCheck, envScan, extractFnoxKeys, findConfigPath, fnoxAvailable, fnoxExport, fnoxGet, formatAliasError, formatPacket, generateKeypair, generateTomlFromScan, isEnvAlias, isSecretAlias, loadCatalog, loadConfig, loadConfigFromCwd, maskValue, matchEnvVar, matchValueShape, parseToml, readConfigFile, readFnoxConfig, readResource, removeSection, renameSection, resolveConfig, resolveConfigPath, resolveInlineKey, resolveKeyPath, resolveSecrets, resolveValues, resourceDefinitions, scanEnv, scanFleet, sealSecrets, startServer, toolDefinitions, unsealSecrets, unwrapAgentKey, updateConfigIdentity, updateSectionFields, validateAliases, validateConfig };
|
|
2682
|
+
export { AgentIdentitySchema, CallbackConfigSchema, ConsumerType, EnvMetaSchema, EnvpktBootError, EnvpktConfigSchema, IdentitySchema, LifecycleConfigSchema, SecretMetaSchema, ToolsConfigSchema, ageAvailable, ageDecrypt, ageEncrypt, appendSection, boot, bootSafe, callTool, compareFnoxAndEnvpkt, computeAudit, computeEnvAudit, createDirectConsoleLogger, createDirectTestLogger, createServer, deriveServiceFromName, detectFnox, directSilentLogger, discoverConfig, envCheck, envScan, extractFnoxKeys, findConfigPath, fnoxAvailable, fnoxExport, fnoxGet, formatAliasError, formatPacket, generateKeypair, generateTomlFromScan, isEnvAlias, isSecretAlias, loadCatalog, loadConfig, loadConfigFromCwd, maskValue, matchEnvVar, matchValueShape, parseToml, readConfigFile, readFnoxConfig, readResource, removeSection, renameSection, resolveConfig, resolveConfigPath, resolveInlineKey, resolveKeyPath, resolveSecrets, resolveValues, resourceDefinitions, scanEnv, scanFleet, sealSecrets, startServer, toolDefinitions, unsealSecrets, unwrapAgentKey, updateConfigIdentity, updateSectionFields, validateAliases, validateConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "envpkt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Credential lifecycle and fleet management for AI agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"credentials",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@sinclair/typebox": "^0.34.49",
|
|
44
44
|
"commander": "^14.0.3",
|
|
45
45
|
"functype": "^0.60.0",
|
|
46
|
+
"functype-log": "^0.60.0",
|
|
46
47
|
"functype-os": "^0.60.0",
|
|
47
48
|
"smol-toml": "^1.6.1"
|
|
48
49
|
},
|