@centient/secrets 0.2.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.
Files changed (57) hide show
  1. package/dist/cli/messages.d.ts +60 -0
  2. package/dist/cli/messages.d.ts.map +1 -0
  3. package/dist/cli/messages.js +63 -0
  4. package/dist/cli/messages.js.map +1 -0
  5. package/dist/cli/secrets-cli.d.ts +38 -0
  6. package/dist/cli/secrets-cli.d.ts.map +1 -0
  7. package/dist/cli/secrets-cli.js +532 -0
  8. package/dist/cli/secrets-cli.js.map +1 -0
  9. package/dist/crypto/vault-common.d.ts +63 -0
  10. package/dist/crypto/vault-common.d.ts.map +1 -0
  11. package/dist/crypto/vault-common.js +180 -0
  12. package/dist/crypto/vault-common.js.map +1 -0
  13. package/dist/environment/EnvironmentManager.d.ts +171 -0
  14. package/dist/environment/EnvironmentManager.d.ts.map +1 -0
  15. package/dist/environment/EnvironmentManager.js +604 -0
  16. package/dist/environment/EnvironmentManager.js.map +1 -0
  17. package/dist/index.d.ts +12 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +17 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/platform/agent-detect.d.ts +15 -0
  22. package/dist/platform/agent-detect.d.ts.map +1 -0
  23. package/dist/platform/agent-detect.js +22 -0
  24. package/dist/platform/agent-detect.js.map +1 -0
  25. package/dist/platform/platform.d.ts +51 -0
  26. package/dist/platform/platform.d.ts.map +1 -0
  27. package/dist/platform/platform.js +141 -0
  28. package/dist/platform/platform.js.map +1 -0
  29. package/dist/vault/types.d.ts +54 -0
  30. package/dist/vault/types.d.ts.map +1 -0
  31. package/dist/vault/types.js +12 -0
  32. package/dist/vault/types.js.map +1 -0
  33. package/dist/vault/vault-env.d.ts +58 -0
  34. package/dist/vault/vault-env.d.ts.map +1 -0
  35. package/dist/vault/vault-env.js +73 -0
  36. package/dist/vault/vault-env.js.map +1 -0
  37. package/dist/vault/vault-gpg.d.ts +40 -0
  38. package/dist/vault/vault-gpg.d.ts.map +1 -0
  39. package/dist/vault/vault-gpg.js +149 -0
  40. package/dist/vault/vault-gpg.js.map +1 -0
  41. package/dist/vault/vault-libsecret.d.ts +51 -0
  42. package/dist/vault/vault-libsecret.d.ts.map +1 -0
  43. package/dist/vault/vault-libsecret.js +115 -0
  44. package/dist/vault/vault-libsecret.js.map +1 -0
  45. package/dist/vault/vault-utils.d.ts +12 -0
  46. package/dist/vault/vault-utils.d.ts.map +1 -0
  47. package/dist/vault/vault-utils.js +16 -0
  48. package/dist/vault/vault-utils.js.map +1 -0
  49. package/dist/vault/vault-windows.d.ts +71 -0
  50. package/dist/vault/vault-windows.d.ts.map +1 -0
  51. package/dist/vault/vault-windows.js +186 -0
  52. package/dist/vault/vault-windows.js.map +1 -0
  53. package/dist/vault/vault.d.ts +53 -0
  54. package/dist/vault/vault.d.ts.map +1 -0
  55. package/dist/vault/vault.js +132 -0
  56. package/dist/vault/vault.js.map +1 -0
  57. package/package.json +37 -0
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Agent Environment Detection
3
+ *
4
+ * Detects whether the process is running inside an AI agent session
5
+ * (Claude Code, MCP context, etc.). Auth commands that require human
6
+ * interaction are blocked in these environments.
7
+ *
8
+ * Shared by: vault.ts, cli, secrets-cli.ts
9
+ */
10
+ /**
11
+ * Returns true if the current process appears to be running inside an
12
+ * AI agent environment (Claude Code, MCP subprocess, etc.).
13
+ */
14
+ export declare function isAgentEnvironment(): boolean;
15
+ //# sourceMappingURL=agent-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-detect.d.ts","sourceRoot":"","sources":["../../src/platform/agent-detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAS5C"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Agent Environment Detection
3
+ *
4
+ * Detects whether the process is running inside an AI agent session
5
+ * (Claude Code, MCP context, etc.). Auth commands that require human
6
+ * interaction are blocked in these environments.
7
+ *
8
+ * Shared by: vault.ts, cli, secrets-cli.ts
9
+ */
10
+ /**
11
+ * Returns true if the current process appears to be running inside an
12
+ * AI agent environment (Claude Code, MCP subprocess, etc.).
13
+ */
14
+ export function isAgentEnvironment() {
15
+ return !!(process.env["CLAUDE_PROJECT_DIR"] ||
16
+ process.env["MCP_CONTEXT"] ||
17
+ process.env["CLAUDE_CODE_SESSION"] ||
18
+ process.env["CLAUDE_CODE_ENTRY_POINT"] ||
19
+ process.env["ANTHROPIC_API_KEY_SOURCE"] ||
20
+ process.env["MCP_SERVER_NAME"]);
21
+ }
22
+ //# sourceMappingURL=agent-detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-detect.js","sourceRoot":"","sources":["../../src/platform/agent-detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,CAAC,CACP,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Auth Platform — Capability Detection
3
+ *
4
+ * Detects terminal/platform capabilities for rendering decisions.
5
+ * All functions are pure (no side effects beyond reading process.env / process.stdout).
6
+ */
7
+ /**
8
+ * Returns true if stdout is a TTY (interactive terminal).
9
+ * Spinner, colour, and unicode output should only be used when this is true.
10
+ */
11
+ export declare function isTTY(): boolean;
12
+ /**
13
+ * Returns true if the terminal likely supports Unicode characters.
14
+ * Detection is based on LANG or LC_ALL containing "UTF-8" (case-insensitive).
15
+ * Falls back to false when environment variables are absent.
16
+ */
17
+ export declare function canUnicode(): boolean;
18
+ /**
19
+ * Returns true if running in a headless environment (no display server).
20
+ *
21
+ * On Linux: checks for absence of DISPLAY and WAYLAND_DISPLAY and
22
+ * XDG_CURRENT_DESKTOP env vars.
23
+ * On macOS: always returns false (macOS always has a window server available
24
+ * even in SSH sessions with X11 forwarding disabled).
25
+ * In CI environments: treats CI=true as headless.
26
+ */
27
+ export declare function isHeadless(): boolean;
28
+ /**
29
+ * Returns true if the system has a browser launcher available.
30
+ *
31
+ * macOS: checks for `open` (always present).
32
+ * Linux: checks for `xdg-open` via `which`.
33
+ * Other: returns false.
34
+ */
35
+ export declare function canLaunchBrowser(): boolean;
36
+ /**
37
+ * Returns true if the process is running in a known CI environment.
38
+ * Checks standard CI environment variables used by common CI platforms.
39
+ */
40
+ export declare function isCIEnvironment(): boolean;
41
+ /**
42
+ * Returns true if the process is running inside a Docker or containerd container.
43
+ * Checks /proc/1/cgroup for container markers and /.dockerenv existence.
44
+ */
45
+ export declare function isDockerContainer(): boolean;
46
+ /**
47
+ * Returns true if the process is running inside an SSH session.
48
+ * Checks SSH_CONNECTION and SSH_CLIENT environment variables.
49
+ */
50
+ export declare function isSSHSession(): boolean;
51
+ //# sourceMappingURL=platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/platform/platform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;;GAGG;AACH,wBAAgB,KAAK,IAAI,OAAO,CAE/B;AAMD;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,OAAO,CASpC;AAMD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAiBpC;AAMD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAkB1C;AAMD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CASzC;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAe3C;AAMD;;;GAGG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Auth Platform — Capability Detection
3
+ *
4
+ * Detects terminal/platform capabilities for rendering decisions.
5
+ * All functions are pure (no side effects beyond reading process.env / process.stdout).
6
+ */
7
+ import { existsSync, readFileSync } from "fs";
8
+ import { execSync } from "child_process";
9
+ // =============================================================================
10
+ // TTY detection
11
+ // =============================================================================
12
+ /**
13
+ * Returns true if stdout is a TTY (interactive terminal).
14
+ * Spinner, colour, and unicode output should only be used when this is true.
15
+ */
16
+ export function isTTY() {
17
+ return process.stdout.isTTY === true;
18
+ }
19
+ // =============================================================================
20
+ // Unicode detection
21
+ // =============================================================================
22
+ /**
23
+ * Returns true if the terminal likely supports Unicode characters.
24
+ * Detection is based on LANG or LC_ALL containing "UTF-8" (case-insensitive).
25
+ * Falls back to false when environment variables are absent.
26
+ */
27
+ export function canUnicode() {
28
+ const lang = process.env["LANG"] ?? "";
29
+ const lcAll = process.env["LC_ALL"] ?? "";
30
+ const lcCtype = process.env["LC_CTYPE"] ?? "";
31
+ return (/utf-?8/i.test(lang) ||
32
+ /utf-?8/i.test(lcAll) ||
33
+ /utf-?8/i.test(lcCtype));
34
+ }
35
+ // =============================================================================
36
+ // Headless detection
37
+ // =============================================================================
38
+ /**
39
+ * Returns true if running in a headless environment (no display server).
40
+ *
41
+ * On Linux: checks for absence of DISPLAY and WAYLAND_DISPLAY and
42
+ * XDG_CURRENT_DESKTOP env vars.
43
+ * On macOS: always returns false (macOS always has a window server available
44
+ * even in SSH sessions with X11 forwarding disabled).
45
+ * In CI environments: treats CI=true as headless.
46
+ */
47
+ export function isHeadless() {
48
+ // Explicit CI flag
49
+ if (process.env["CI"] === "true" || process.env["CI"] === "1")
50
+ return true;
51
+ // macOS has a window server; treat as non-headless unless CI
52
+ if (process.platform === "darwin")
53
+ return false;
54
+ // Linux: headless if no display server variables are set
55
+ if (process.platform === "linux") {
56
+ const hasDisplay = Boolean(process.env["DISPLAY"]);
57
+ const hasWayland = Boolean(process.env["WAYLAND_DISPLAY"]);
58
+ const hasDesktop = Boolean(process.env["XDG_CURRENT_DESKTOP"]);
59
+ return !hasDisplay && !hasWayland && !hasDesktop;
60
+ }
61
+ // Unknown platform — assume headless for safety
62
+ return true;
63
+ }
64
+ // =============================================================================
65
+ // Browser launch detection
66
+ // =============================================================================
67
+ /**
68
+ * Returns true if the system has a browser launcher available.
69
+ *
70
+ * macOS: checks for `open` (always present).
71
+ * Linux: checks for `xdg-open` via `which`.
72
+ * Other: returns false.
73
+ */
74
+ export function canLaunchBrowser() {
75
+ if (isHeadless())
76
+ return false;
77
+ try {
78
+ if (process.platform === "darwin") {
79
+ execSync("which open", { stdio: "pipe" });
80
+ return true;
81
+ }
82
+ if (process.platform === "linux") {
83
+ execSync("which xdg-open", { stdio: "pipe" });
84
+ return true;
85
+ }
86
+ }
87
+ catch {
88
+ // `which` returned non-zero — tool not found
89
+ }
90
+ return false;
91
+ }
92
+ // =============================================================================
93
+ // CI environment detection
94
+ // =============================================================================
95
+ /**
96
+ * Returns true if the process is running in a known CI environment.
97
+ * Checks standard CI environment variables used by common CI platforms.
98
+ */
99
+ export function isCIEnvironment() {
100
+ return !!(process.env["CI"] ||
101
+ process.env["GITHUB_ACTIONS"] ||
102
+ process.env["GITLAB_CI"] ||
103
+ process.env["CIRCLECI"] ||
104
+ process.env["TRAVIS"] ||
105
+ process.env["BUILDKITE"]);
106
+ }
107
+ // =============================================================================
108
+ // Docker/container detection
109
+ // =============================================================================
110
+ /**
111
+ * Returns true if the process is running inside a Docker or containerd container.
112
+ * Checks /proc/1/cgroup for container markers and /.dockerenv existence.
113
+ */
114
+ export function isDockerContainer() {
115
+ // Check for /.dockerenv (Docker-specific file)
116
+ if (existsSync("/.dockerenv"))
117
+ return true;
118
+ // Check /proc/1/cgroup for docker or containerd markers (Linux only)
119
+ if (process.platform === "linux") {
120
+ try {
121
+ const cgroup = readFileSync("/proc/1/cgroup", "utf8");
122
+ if (/docker|containerd/.test(cgroup))
123
+ return true;
124
+ }
125
+ catch {
126
+ // /proc/1/cgroup not readable — not a concern on non-Linux
127
+ }
128
+ }
129
+ return false;
130
+ }
131
+ // =============================================================================
132
+ // SSH session detection
133
+ // =============================================================================
134
+ /**
135
+ * Returns true if the process is running inside an SSH session.
136
+ * Checks SSH_CONNECTION and SSH_CLIENT environment variables.
137
+ */
138
+ export function isSSHSession() {
139
+ return !!(process.env["SSH_CONNECTION"] || process.env["SSH_CLIENT"]);
140
+ }
141
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/platform/platform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Auth Module — Shared Type Definitions
3
+ */
4
+ export interface TokenValidationResult {
5
+ valid: boolean;
6
+ status: "valid" | "expiring_soon" | "expired";
7
+ expiresAt: Date | null;
8
+ remainingMs: number;
9
+ formattedRemaining: string;
10
+ }
11
+ export interface DeviceFlowConfig {
12
+ /** Base URL for the auth API (e.g. https://api.engram.ai) */
13
+ baseUrl: string;
14
+ /** OAuth client ID */
15
+ clientId?: string;
16
+ /** Poll timeout in seconds (default: 300) */
17
+ timeoutSeconds?: number;
18
+ }
19
+ export interface DeviceFlowResult {
20
+ accessToken: string;
21
+ refreshToken: string;
22
+ expiresAt: Date;
23
+ }
24
+ export type DeviceFlowErrorCode = "access_denied" | "expired_token" | "network_error" | "timeout" | "unknown";
25
+ export declare class DeviceFlowError extends Error {
26
+ readonly code: DeviceFlowErrorCode;
27
+ constructor(code: DeviceFlowErrorCode, message: string);
28
+ }
29
+ export interface SpinnerHandle {
30
+ /** Update the spinner message */
31
+ update(message: string): void;
32
+ /** Stop the spinner and optionally print a final line */
33
+ stop(finalMessage?: string): void;
34
+ }
35
+ export interface CountdownHandle {
36
+ /** Cancel the countdown early */
37
+ cancel(): void;
38
+ }
39
+ export type VaultType = "keychain" | "windows" | "libsecret" | "gpg" | "env" | "unknown";
40
+ export interface StoredCredentialMeta {
41
+ source: "device-flow" | "api-key" | "env";
42
+ storedAt: string;
43
+ refreshToken?: string;
44
+ }
45
+ /**
46
+ * Common interface implemented by all vault backends.
47
+ * Backends must implement store/retrieve/delete plus a static detect() method.
48
+ */
49
+ export interface VaultBackend {
50
+ store(key: string, value: string): boolean;
51
+ retrieve(key: string): string | null;
52
+ delete(key: string): boolean;
53
+ }
54
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vault/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAAC;IAC9C,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,eAAe,GACf,eAAe,GACf,SAAS,GACT,SAAS,CAAC;AAEd,qBAAa,eAAgB,SAAQ,KAAK;aAEtB,IAAI,EAAE,mBAAmB;gBAAzB,IAAI,EAAE,mBAAmB,EACzC,OAAO,EAAE,MAAM;CAKlB;AAMD,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yDAAyD;IACzD,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,MAAM,IAAI,IAAI,CAAC;CAChB;AAMD,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;AAEzF,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,KAAK,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC9B"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Auth Module — Shared Type Definitions
3
+ */
4
+ export class DeviceFlowError extends Error {
5
+ code;
6
+ constructor(code, message) {
7
+ super(message);
8
+ this.code = code;
9
+ this.name = "DeviceFlowError";
10
+ }
11
+ }
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/vault/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwCH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAEtB;IADlB,YACkB,IAAyB,EACzC,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAqB;QAIzC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Auth Vault — Environment Variable Fallback Backend
3
+ *
4
+ * Last-resort vault backend that reads credentials from environment variables.
5
+ * Reads/writes nothing to disk. Suitable for CI/headless environments where no
6
+ * secure credential store (libsecret, GPG, macOS Keychain) is available.
7
+ *
8
+ * Implements the VaultBackend interface:
9
+ * store(key, value): boolean — always returns false (env vars are read-only)
10
+ * retrieve(key): string|null — returns ENGRAM_API_KEY for 'auth-token', null otherwise
11
+ * delete(key): boolean — always returns true (no-op; nothing to delete)
12
+ * static detect(): boolean — always returns true (last-resort fallback)
13
+ */
14
+ import type { VaultBackend } from "./types.js";
15
+ /**
16
+ * Environment-variable-only vault backend.
17
+ *
18
+ * This is the last-resort fallback when no OS-level secure credential store is
19
+ * available. It surfaces `ENGRAM_API_KEY` as the `auth-token` credential and
20
+ * rejects all write attempts with a warning on stderr.
21
+ */
22
+ export declare class EnvVault implements VaultBackend {
23
+ /**
24
+ * Detection probe — always returns true so that EnvVault is always
25
+ * available as a last-resort fallback.
26
+ */
27
+ static detect(): boolean;
28
+ /**
29
+ * Attempt to store a credential.
30
+ *
31
+ * Environment variables cannot be written from within a process, so this
32
+ * always fails. A warning is emitted to stderr explaining how to configure
33
+ * persistent storage.
34
+ *
35
+ * @returns false — storage is never performed
36
+ */
37
+ store(_key: string, _value: string): boolean;
38
+ /**
39
+ * Retrieve a credential from the environment.
40
+ *
41
+ * - `'auth-token'` -> `process.env["ENGRAM_API_KEY"] ?? null`
42
+ * - `'refresh-token'` -> `null` (refresh tokens are not available in env mode)
43
+ * - any other key -> `null`
44
+ *
45
+ * @param key - Logical credential key
46
+ * @returns The credential value, or null if unavailable
47
+ */
48
+ retrieve(key: string): string | null;
49
+ /**
50
+ * Delete a credential.
51
+ *
52
+ * No-op: there is nothing stored in this backend to delete.
53
+ *
54
+ * @returns true — always succeeds (nothing to remove)
55
+ */
56
+ delete(_key: string): boolean;
57
+ }
58
+ //# sourceMappingURL=vault-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-env.d.ts","sourceRoot":"","sources":["../../src/vault/vault-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C;;;;;;GAMG;AACH,qBAAa,QAAS,YAAW,YAAY;IAC3C;;;OAGG;IACH,MAAM,CAAC,MAAM,IAAI,OAAO;IAIxB;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAK5C;;;;;;;;;OASG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAOpC;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAG9B"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Auth Vault — Environment Variable Fallback Backend
3
+ *
4
+ * Last-resort vault backend that reads credentials from environment variables.
5
+ * Reads/writes nothing to disk. Suitable for CI/headless environments where no
6
+ * secure credential store (libsecret, GPG, macOS Keychain) is available.
7
+ *
8
+ * Implements the VaultBackend interface:
9
+ * store(key, value): boolean — always returns false (env vars are read-only)
10
+ * retrieve(key): string|null — returns ENGRAM_API_KEY for 'auth-token', null otherwise
11
+ * delete(key): boolean — always returns true (no-op; nothing to delete)
12
+ * static detect(): boolean — always returns true (last-resort fallback)
13
+ */
14
+ import { AUTH_MESSAGES } from "../cli/messages.js";
15
+ // =============================================================================
16
+ // EnvVault implementation
17
+ // =============================================================================
18
+ /**
19
+ * Environment-variable-only vault backend.
20
+ *
21
+ * This is the last-resort fallback when no OS-level secure credential store is
22
+ * available. It surfaces `ENGRAM_API_KEY` as the `auth-token` credential and
23
+ * rejects all write attempts with a warning on stderr.
24
+ */
25
+ export class EnvVault {
26
+ /**
27
+ * Detection probe — always returns true so that EnvVault is always
28
+ * available as a last-resort fallback.
29
+ */
30
+ static detect() {
31
+ return true;
32
+ }
33
+ /**
34
+ * Attempt to store a credential.
35
+ *
36
+ * Environment variables cannot be written from within a process, so this
37
+ * always fails. A warning is emitted to stderr explaining how to configure
38
+ * persistent storage.
39
+ *
40
+ * @returns false — storage is never performed
41
+ */
42
+ store(_key, _value) {
43
+ process.stderr.write(AUTH_MESSAGES.warning.envVaultNoStorage + "\n");
44
+ return false;
45
+ }
46
+ /**
47
+ * Retrieve a credential from the environment.
48
+ *
49
+ * - `'auth-token'` -> `process.env["ENGRAM_API_KEY"] ?? null`
50
+ * - `'refresh-token'` -> `null` (refresh tokens are not available in env mode)
51
+ * - any other key -> `null`
52
+ *
53
+ * @param key - Logical credential key
54
+ * @returns The credential value, or null if unavailable
55
+ */
56
+ retrieve(key) {
57
+ if (key === "auth-token") {
58
+ return process.env["ENGRAM_API_KEY"] ?? null;
59
+ }
60
+ return null;
61
+ }
62
+ /**
63
+ * Delete a credential.
64
+ *
65
+ * No-op: there is nothing stored in this backend to delete.
66
+ *
67
+ * @returns true — always succeeds (nothing to remove)
68
+ */
69
+ delete(_key) {
70
+ return true;
71
+ }
72
+ }
73
+ //# sourceMappingURL=vault-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-env.js","sourceRoot":"","sources":["../../src/vault/vault-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,gFAAgF;AAChF,0BAA0B;AAC1B,gFAAgF;AAEhF;;;;;;GAMG;AACH,MAAM,OAAO,QAAQ;IACnB;;;OAGG;IACH,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAY,EAAE,MAAc;QAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;;OASG;IACH,QAAQ,CAAC,GAAW;QAClB,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;YACzB,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC;QAC/C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,IAAY;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Auth Vault — GPG Backend
3
+ *
4
+ * Implements the VaultBackend interface using GPG-encrypted files stored at
5
+ * ~/.centient/auth/credentials-<key>.gpg. Falls back gracefully when GPG is
6
+ * not installed or no keys are configured.
7
+ *
8
+ * Error handling: all methods return false/null on failure — never throw.
9
+ */
10
+ import type { VaultBackend } from "./types.js";
11
+ /**
12
+ * Vault backend that stores credentials as GPG-encrypted files.
13
+ *
14
+ * Use `GpgVault.detect()` before instantiating to verify availability.
15
+ */
16
+ export declare class GpgVault implements VaultBackend {
17
+ /**
18
+ * Returns true if GPG is installed and at least one public key is available.
19
+ */
20
+ static detect(): boolean;
21
+ /**
22
+ * Encrypts and stores `value` under `key` using the first available GPG key.
23
+ *
24
+ * @returns true on success, false if GPG is unavailable or encryption fails
25
+ */
26
+ store(key: string, value: string): boolean;
27
+ /**
28
+ * Decrypts and returns the stored credential for `key`.
29
+ *
30
+ * @returns the plaintext credential, or null if not found / decryption fails
31
+ */
32
+ retrieve(key: string): string | null;
33
+ /**
34
+ * Deletes the GPG-encrypted credential file for `key`.
35
+ *
36
+ * @returns true if the file was deleted or did not exist, false on unexpected error
37
+ */
38
+ delete(key: string): boolean;
39
+ }
40
+ //# sourceMappingURL=vault-gpg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-gpg.d.ts","sourceRoot":"","sources":["../../src/vault/vault-gpg.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA4D/C;;;;GAIG;AACH,qBAAa,QAAS,YAAW,YAAY;IAC3C;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,OAAO;IASxB;;;;OAIG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAuB1C;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAkBpC;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAkB7B"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Auth Vault — GPG Backend
3
+ *
4
+ * Implements the VaultBackend interface using GPG-encrypted files stored at
5
+ * ~/.centient/auth/credentials-<key>.gpg. Falls back gracefully when GPG is
6
+ * not installed or no keys are configured.
7
+ *
8
+ * Error handling: all methods return false/null on failure — never throw.
9
+ */
10
+ import { execFileSync } from "child_process";
11
+ import { mkdirSync, unlinkSync } from "fs";
12
+ import { homedir } from "os";
13
+ import { join } from "path";
14
+ import { isValidKey } from "./vault-utils.js";
15
+ // =============================================================================
16
+ // Constants
17
+ // =============================================================================
18
+ const AUTH_DIR = join(homedir(), ".centient", "auth");
19
+ // =============================================================================
20
+ // Helpers
21
+ // =============================================================================
22
+ /**
23
+ * Returns the path to the GPG-encrypted credential file for the given key.
24
+ */
25
+ function credentialPath(key) {
26
+ return join(AUTH_DIR, `credentials-${key}.gpg`);
27
+ }
28
+ /**
29
+ * Ensures ~/.centient/auth/ exists.
30
+ */
31
+ function ensureAuthDir() {
32
+ mkdirSync(AUTH_DIR, { recursive: true });
33
+ }
34
+ /**
35
+ * Parses `gpg --list-keys --with-colons` output and returns the fingerprint
36
+ * of the first available public key, or null if none found.
37
+ */
38
+ function getFirstGpgKeyId() {
39
+ try {
40
+ const output = execFileSync("gpg", ["--list-keys", "--with-colons"], { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
41
+ const lines = output.split("\n");
42
+ for (const line of lines) {
43
+ if (line.startsWith("fpr:")) {
44
+ // fpr lines have the fingerprint in the 10th colon-delimited field (index 9)
45
+ const parts = line.split(":");
46
+ const fingerprint = parts[9];
47
+ if (!fingerprint || !/^[0-9A-Fa-f]{40}$/.test(fingerprint.trim()))
48
+ continue;
49
+ if (fingerprint && fingerprint.trim().length > 0) {
50
+ return fingerprint.trim();
51
+ }
52
+ }
53
+ }
54
+ return null;
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ // =============================================================================
61
+ // GpgVault
62
+ // =============================================================================
63
+ /**
64
+ * Vault backend that stores credentials as GPG-encrypted files.
65
+ *
66
+ * Use `GpgVault.detect()` before instantiating to verify availability.
67
+ */
68
+ export class GpgVault {
69
+ /**
70
+ * Returns true if GPG is installed and at least one public key is available.
71
+ */
72
+ static detect() {
73
+ try {
74
+ execFileSync("which", ["gpg"], { stdio: ["pipe", "pipe", "pipe"] });
75
+ }
76
+ catch {
77
+ return false;
78
+ }
79
+ return getFirstGpgKeyId() !== null;
80
+ }
81
+ /**
82
+ * Encrypts and stores `value` under `key` using the first available GPG key.
83
+ *
84
+ * @returns true on success, false if GPG is unavailable or encryption fails
85
+ */
86
+ store(key, value) {
87
+ if (!isValidKey(key))
88
+ return false;
89
+ try {
90
+ const keyId = getFirstGpgKeyId();
91
+ if (keyId === null)
92
+ return false;
93
+ ensureAuthDir();
94
+ const outPath = credentialPath(key);
95
+ execFileSync("gpg", ["--batch", "--yes", "-e", "-r", keyId, "-o", outPath], {
96
+ input: value,
97
+ stdio: ["pipe", "pipe", "pipe"],
98
+ });
99
+ return true;
100
+ }
101
+ catch {
102
+ return false;
103
+ }
104
+ }
105
+ /**
106
+ * Decrypts and returns the stored credential for `key`.
107
+ *
108
+ * @returns the plaintext credential, or null if not found / decryption fails
109
+ */
110
+ retrieve(key) {
111
+ if (!isValidKey(key))
112
+ return null;
113
+ try {
114
+ const filePath = credentialPath(key);
115
+ const result = execFileSync("gpg", ["--batch", "--quiet", "-d", filePath], {
116
+ encoding: "utf8",
117
+ stdio: ["pipe", "pipe", "pipe"],
118
+ });
119
+ return result ?? null;
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ /**
126
+ * Deletes the GPG-encrypted credential file for `key`.
127
+ *
128
+ * @returns true if the file was deleted or did not exist, false on unexpected error
129
+ */
130
+ delete(key) {
131
+ if (!isValidKey(key))
132
+ return false;
133
+ try {
134
+ unlinkSync(credentialPath(key));
135
+ return true;
136
+ }
137
+ catch (err) {
138
+ // ENOENT means file did not exist — treat as success
139
+ if (err !== null &&
140
+ typeof err === "object" &&
141
+ "code" in err &&
142
+ err.code === "ENOENT") {
143
+ return true;
144
+ }
145
+ return false;
146
+ }
147
+ }
148
+ }
149
+ //# sourceMappingURL=vault-gpg.js.map