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 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
- return resolveAndLoad(opts).flatMap(({ config, configPath, configDir, configSource }) => validateAliases(config).fold((err) => Left(err), (aliasTable) => {
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.map(([key]) => key).forEach((key) => sealedKeys.add(key));
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
- } else skipped.push(aliasKey);
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
- return resolveAndLoad(opts).flatMap(({ config, configPath, configDir, configSource }) => validateAliases(config).fold((err) => Left(err), (aliasTable) => {
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.map(([key]) => key).forEach((key) => sealedKeys.add(key));
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
- } else skipped.push(aliasKey);
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.10.2",
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
  },