passwd-sso-cli 0.4.3

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 (63) hide show
  1. package/dist/commands/agent-decrypt.d.ts +11 -0
  2. package/dist/commands/agent-decrypt.js +317 -0
  3. package/dist/commands/agent.d.ts +13 -0
  4. package/dist/commands/agent.js +116 -0
  5. package/dist/commands/api-key.d.ts +22 -0
  6. package/dist/commands/api-key.js +118 -0
  7. package/dist/commands/decrypt.d.ts +17 -0
  8. package/dist/commands/decrypt.js +108 -0
  9. package/dist/commands/env.d.ts +15 -0
  10. package/dist/commands/env.js +102 -0
  11. package/dist/commands/export.d.ts +7 -0
  12. package/dist/commands/export.js +99 -0
  13. package/dist/commands/generate.d.ts +11 -0
  14. package/dist/commands/generate.js +45 -0
  15. package/dist/commands/get.d.ts +8 -0
  16. package/dist/commands/get.js +73 -0
  17. package/dist/commands/list.d.ts +6 -0
  18. package/dist/commands/list.js +66 -0
  19. package/dist/commands/login.d.ts +4 -0
  20. package/dist/commands/login.js +45 -0
  21. package/dist/commands/run.d.ts +12 -0
  22. package/dist/commands/run.js +97 -0
  23. package/dist/commands/status.d.ts +6 -0
  24. package/dist/commands/status.js +62 -0
  25. package/dist/commands/totp.d.ts +7 -0
  26. package/dist/commands/totp.js +57 -0
  27. package/dist/commands/unlock.d.ts +19 -0
  28. package/dist/commands/unlock.js +125 -0
  29. package/dist/index.d.ts +8 -0
  30. package/dist/index.js +298 -0
  31. package/dist/lib/api-client.d.ts +22 -0
  32. package/dist/lib/api-client.js +145 -0
  33. package/dist/lib/blocked-keys.d.ts +2 -0
  34. package/dist/lib/blocked-keys.js +23 -0
  35. package/dist/lib/clipboard.d.ts +8 -0
  36. package/dist/lib/clipboard.js +79 -0
  37. package/dist/lib/config.d.ts +18 -0
  38. package/dist/lib/config.js +110 -0
  39. package/dist/lib/crypto-aad.d.ts +5 -0
  40. package/dist/lib/crypto-aad.js +44 -0
  41. package/dist/lib/crypto.d.ts +23 -0
  42. package/dist/lib/crypto.js +148 -0
  43. package/dist/lib/migrate.d.ts +8 -0
  44. package/dist/lib/migrate.js +87 -0
  45. package/dist/lib/openssh-key-parser.d.ts +17 -0
  46. package/dist/lib/openssh-key-parser.js +273 -0
  47. package/dist/lib/output.d.ts +10 -0
  48. package/dist/lib/output.js +36 -0
  49. package/dist/lib/paths.d.ts +17 -0
  50. package/dist/lib/paths.js +39 -0
  51. package/dist/lib/secrets-config.d.ts +31 -0
  52. package/dist/lib/secrets-config.js +48 -0
  53. package/dist/lib/ssh-agent-protocol.d.ts +56 -0
  54. package/dist/lib/ssh-agent-protocol.js +108 -0
  55. package/dist/lib/ssh-agent-socket.d.ts +20 -0
  56. package/dist/lib/ssh-agent-socket.js +187 -0
  57. package/dist/lib/ssh-key-agent.d.ts +54 -0
  58. package/dist/lib/ssh-key-agent.js +197 -0
  59. package/dist/lib/totp.d.ts +10 -0
  60. package/dist/lib/totp.js +31 -0
  61. package/dist/lib/vault-state.d.ts +15 -0
  62. package/dist/lib/vault-state.js +37 -0
  63. package/package.json +56 -0
@@ -0,0 +1,187 @@
1
+ /**
2
+ * SSH agent Unix domain socket server.
3
+ *
4
+ * Creates a Unix socket that implements the SSH agent protocol,
5
+ * serving keys from the passwd-sso vault.
6
+ */
7
+ import { createServer } from "node:net";
8
+ import { mkdirSync, lstatSync, chmodSync, unlinkSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { readUint32, readString, SSH2_AGENTC_REQUEST_IDENTITIES, SSH2_AGENTC_SIGN_REQUEST, buildFailure, buildIdentitiesAnswer, buildSignResponse, } from "./ssh-agent-protocol.js";
11
+ import { getLoadedKeys, findKeyByBlob, signData } from "./ssh-key-agent.js";
12
+ let server = null;
13
+ let socketPath = null;
14
+ /**
15
+ * Get the socket directory path.
16
+ * Prefers $XDG_RUNTIME_DIR/passwd-sso/, falls back to /tmp/passwd-sso-<uid>/
17
+ */
18
+ function getSocketDir() {
19
+ const xdg = process.env.XDG_RUNTIME_DIR;
20
+ if (xdg)
21
+ return join(xdg, "passwd-sso");
22
+ const uid = process.getuid?.();
23
+ if (uid === undefined) {
24
+ throw new Error("Cannot determine user ID for socket directory");
25
+ }
26
+ return join("/tmp", `passwd-sso-${uid}`);
27
+ }
28
+ /**
29
+ * Create the socket directory with proper permissions.
30
+ * Validates ownership and mode to prevent symlink attacks.
31
+ */
32
+ function ensureSocketDir(dir) {
33
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
34
+ // Verify ownership and permissions (TOCTOU mitigation — lstatSync to avoid following symlinks)
35
+ const stat = lstatSync(dir);
36
+ if (!stat.isDirectory()) {
37
+ throw new Error(`Socket path ${dir} is not a directory (possible symlink attack)`);
38
+ }
39
+ const uid = process.getuid?.();
40
+ if (uid !== undefined && stat.uid !== uid) {
41
+ throw new Error(`Socket directory ${dir} is owned by uid ${stat.uid}, expected ${uid}`);
42
+ }
43
+ const mode = stat.mode & 0o7777;
44
+ if (mode !== 0o700) {
45
+ throw new Error(`Socket directory ${dir} has mode ${mode.toString(8)}, expected 700`);
46
+ }
47
+ }
48
+ /**
49
+ * Handle a single SSH agent protocol message.
50
+ */
51
+ function handleMessage(msgBuf) {
52
+ if (msgBuf.length < 1)
53
+ return buildFailure();
54
+ const msgType = msgBuf[0];
55
+ switch (msgType) {
56
+ case SSH2_AGENTC_REQUEST_IDENTITIES: {
57
+ const keys = getLoadedKeys();
58
+ return buildIdentitiesAnswer(keys.map((k) => ({
59
+ publicKeyBlob: k.publicKeyBlob,
60
+ comment: k.comment,
61
+ })));
62
+ }
63
+ case SSH2_AGENTC_SIGN_REQUEST: {
64
+ try {
65
+ let offset = 1;
66
+ // Read key blob
67
+ const { data: keyBlob, nextOffset: afterKey } = readString(msgBuf, offset);
68
+ offset = afterKey;
69
+ // Read data to sign
70
+ const { data, nextOffset: afterData } = readString(msgBuf, offset);
71
+ offset = afterData;
72
+ // Read flags
73
+ const flags = offset + 4 <= msgBuf.length
74
+ ? readUint32(msgBuf, offset)
75
+ : 0;
76
+ // Find the key
77
+ const key = findKeyByBlob(keyBlob);
78
+ if (!key)
79
+ return buildFailure();
80
+ // Perform signing
81
+ const signature = signData(key, data, flags);
82
+ return buildSignResponse(signature);
83
+ }
84
+ catch {
85
+ return buildFailure();
86
+ }
87
+ }
88
+ default:
89
+ return buildFailure();
90
+ }
91
+ }
92
+ /**
93
+ * Handle data from a connected client.
94
+ * SSH agent protocol uses length-prefixed messages.
95
+ */
96
+ function handleConnection(socket) {
97
+ let buffer = Buffer.alloc(0);
98
+ socket.on("data", (chunk) => {
99
+ buffer = Buffer.concat([buffer, chunk]);
100
+ // Process complete messages
101
+ while (buffer.length >= 4) {
102
+ const msgLen = readUint32(buffer, 0);
103
+ // Reject absurdly large messages (DoS protection)
104
+ if (msgLen > 256 * 1024) {
105
+ socket.destroy();
106
+ return;
107
+ }
108
+ if (buffer.length < 4 + msgLen)
109
+ break; // Need more data
110
+ const msgBuf = buffer.subarray(4, 4 + msgLen);
111
+ buffer = buffer.subarray(4 + msgLen);
112
+ const response = handleMessage(msgBuf);
113
+ socket.write(response);
114
+ }
115
+ });
116
+ socket.on("error", () => {
117
+ // Silently handle client disconnects
118
+ });
119
+ }
120
+ /**
121
+ * Start the SSH agent socket server.
122
+ *
123
+ * @returns The socket path for SSH_AUTH_SOCK
124
+ */
125
+ export function startAgent() {
126
+ if (process.platform === "win32") {
127
+ throw new Error("SSH agent is not supported on Windows. Unix domain sockets are required.");
128
+ }
129
+ if (server) {
130
+ throw new Error("SSH agent is already running");
131
+ }
132
+ const dir = getSocketDir();
133
+ ensureSocketDir(dir);
134
+ const path = join(dir, `agent.${process.pid}.sock`);
135
+ // Clean up stale socket file
136
+ try {
137
+ unlinkSync(path);
138
+ }
139
+ catch {
140
+ // File doesn't exist, that's fine
141
+ }
142
+ server = createServer(handleConnection);
143
+ server.listen(path, () => {
144
+ // Set socket file permissions to owner-only
145
+ chmodSync(path, 0o600);
146
+ });
147
+ socketPath = path;
148
+ // Clean up on process exit
149
+ const cleanup = () => {
150
+ stopAgent();
151
+ };
152
+ process.on("exit", cleanup);
153
+ process.on("SIGINT", () => {
154
+ cleanup();
155
+ process.exit(0);
156
+ });
157
+ process.on("SIGTERM", () => {
158
+ cleanup();
159
+ process.exit(0);
160
+ });
161
+ return path;
162
+ }
163
+ /**
164
+ * Stop the SSH agent socket server.
165
+ */
166
+ export function stopAgent() {
167
+ if (server) {
168
+ server.close();
169
+ server = null;
170
+ }
171
+ if (socketPath) {
172
+ try {
173
+ unlinkSync(socketPath);
174
+ }
175
+ catch {
176
+ // Already cleaned up
177
+ }
178
+ socketPath = null;
179
+ }
180
+ }
181
+ /**
182
+ * Get the current socket path, or null if not running.
183
+ */
184
+ export function getSocketPath() {
185
+ return socketPath;
186
+ }
187
+ //# sourceMappingURL=ssh-agent-socket.js.map
@@ -0,0 +1,54 @@
1
+ /**
2
+ * SSH key agent — PEM parsing + signing using Node.js crypto.
3
+ *
4
+ * Manages loaded SSH keys and performs signing operations for the
5
+ * SSH agent protocol.
6
+ */
7
+ import type { KeyObject } from "node:crypto";
8
+ export interface LoadedSshKey {
9
+ /** Entry ID from the vault */
10
+ entryId: string;
11
+ /** PEM-encoded private key */
12
+ pem: string;
13
+ /** Optional passphrase for encrypted keys */
14
+ passphrase?: string;
15
+ /** SSH public key blob (for identity listing) */
16
+ publicKeyBlob: Buffer;
17
+ /** Key comment (usually user@host) */
18
+ comment: string;
19
+ /** Node.js KeyObject (parsed from PEM) */
20
+ keyObject: KeyObject;
21
+ /** Key type identifier */
22
+ keyType: "ed25519" | "rsa" | "ecdsa-sha2-nistp256" | "ecdsa-sha2-nistp384" | "ecdsa-sha2-nistp521";
23
+ }
24
+ /**
25
+ * Load a PEM private key into memory.
26
+ *
27
+ * @returns The public key blob for identity listing
28
+ */
29
+ export declare function loadKey(entryId: string, pem: string, publicKeyBlob: Buffer, comment: string, passphrase?: string): Promise<LoadedSshKey>;
30
+ /**
31
+ * Get all loaded keys for identity listing.
32
+ */
33
+ export declare function getLoadedKeys(): LoadedSshKey[];
34
+ /**
35
+ * Find a loaded key by its public key blob.
36
+ */
37
+ export declare function findKeyByBlob(publicKeyBlob: Buffer): LoadedSshKey | undefined;
38
+ /**
39
+ * Clear all loaded keys and release references.
40
+ *
41
+ * Note: JavaScript strings are immutable — we cannot zero key.pem in-place.
42
+ * We clear object references so GC can collect them sooner, but the original
43
+ * string data may persist in V8 heap until garbage collected.
44
+ */
45
+ export declare function clearKeys(): void;
46
+ /**
47
+ * Sign data with a loaded key using the SSH agent protocol conventions.
48
+ *
49
+ * @param key The loaded key to sign with
50
+ * @param data The data to sign
51
+ * @param flags SSH agent flags (for RSA algorithm selection)
52
+ * @returns The SSH-formatted signature blob
53
+ */
54
+ export declare function signData(key: LoadedSshKey, data: Buffer, flags: number): Buffer;
@@ -0,0 +1,197 @@
1
+ /**
2
+ * SSH key agent — PEM parsing + signing using Node.js crypto.
3
+ *
4
+ * Manages loaded SSH keys and performs signing operations for the
5
+ * SSH agent protocol.
6
+ */
7
+ import { createPrivateKey, createSign, sign as cryptoSign } from "node:crypto";
8
+ import { encodeString, SSH_AGENT_RSA_SHA2_256, SSH_AGENT_RSA_SHA2_512, } from "./ssh-agent-protocol.js";
9
+ import { parseOpenSshPrivateKey } from "./openssh-key-parser.js";
10
+ const loadedKeys = new Map();
11
+ /**
12
+ * Load a PEM private key into memory.
13
+ *
14
+ * @returns The public key blob for identity listing
15
+ */
16
+ export async function loadKey(entryId, pem, publicKeyBlob, comment, passphrase) {
17
+ let keyObject;
18
+ try {
19
+ keyObject = createPrivateKey({
20
+ key: pem,
21
+ ...(passphrase ? { passphrase } : {}),
22
+ });
23
+ }
24
+ catch {
25
+ // Fallback: manually parse OpenSSH format keys (handles encrypted keys)
26
+ keyObject = await parseOpenSshPrivateKey(pem, passphrase);
27
+ }
28
+ const keyType = detectKeyType(keyObject);
29
+ const loaded = {
30
+ entryId,
31
+ pem,
32
+ passphrase,
33
+ publicKeyBlob,
34
+ comment,
35
+ keyObject,
36
+ keyType,
37
+ };
38
+ loadedKeys.set(entryId, loaded);
39
+ return loaded;
40
+ }
41
+ /**
42
+ * Get all loaded keys for identity listing.
43
+ */
44
+ export function getLoadedKeys() {
45
+ return Array.from(loadedKeys.values());
46
+ }
47
+ /**
48
+ * Find a loaded key by its public key blob.
49
+ */
50
+ export function findKeyByBlob(publicKeyBlob) {
51
+ for (const key of loadedKeys.values()) {
52
+ if (key.publicKeyBlob.equals(publicKeyBlob)) {
53
+ return key;
54
+ }
55
+ }
56
+ return undefined;
57
+ }
58
+ /**
59
+ * Clear all loaded keys and release references.
60
+ *
61
+ * Note: JavaScript strings are immutable — we cannot zero key.pem in-place.
62
+ * We clear object references so GC can collect them sooner, but the original
63
+ * string data may persist in V8 heap until garbage collected.
64
+ */
65
+ export function clearKeys() {
66
+ for (const key of loadedKeys.values()) {
67
+ // Drop references to sensitive data (JS strings are immutable, cannot zero)
68
+ key.keyObject = undefined;
69
+ key.pem = "";
70
+ key.passphrase = undefined;
71
+ }
72
+ loadedKeys.clear();
73
+ }
74
+ /**
75
+ * Sign data with a loaded key using the SSH agent protocol conventions.
76
+ *
77
+ * @param key The loaded key to sign with
78
+ * @param data The data to sign
79
+ * @param flags SSH agent flags (for RSA algorithm selection)
80
+ * @returns The SSH-formatted signature blob
81
+ */
82
+ export function signData(key, data, flags) {
83
+ switch (key.keyType) {
84
+ case "ed25519": {
85
+ const sig = cryptoSign(null, data, key.keyObject);
86
+ return Buffer.concat([
87
+ encodeString("ssh-ed25519"),
88
+ encodeString(sig),
89
+ ]);
90
+ }
91
+ case "rsa": {
92
+ const algo = flags & SSH_AGENT_RSA_SHA2_512
93
+ ? "sha512"
94
+ : flags & SSH_AGENT_RSA_SHA2_256
95
+ ? "sha256"
96
+ : "sha256"; // Default to SHA-256 for modern SSH
97
+ const algoName = algo === "sha512"
98
+ ? "rsa-sha2-512"
99
+ : "rsa-sha2-256";
100
+ const signer = createSign(algo);
101
+ signer.update(data);
102
+ const sig = signer.sign(key.keyObject);
103
+ return Buffer.concat([
104
+ encodeString(algoName),
105
+ encodeString(sig),
106
+ ]);
107
+ }
108
+ case "ecdsa-sha2-nistp256":
109
+ case "ecdsa-sha2-nistp384":
110
+ case "ecdsa-sha2-nistp521": {
111
+ const hashMap = {
112
+ "ecdsa-sha2-nistp256": "sha256",
113
+ "ecdsa-sha2-nistp384": "sha384",
114
+ "ecdsa-sha2-nistp521": "sha512",
115
+ };
116
+ const hash = hashMap[key.keyType];
117
+ const signer = createSign(hash);
118
+ signer.update(data);
119
+ // ECDSA sign returns DER-encoded signature by default
120
+ const derSig = signer.sign(key.keyObject);
121
+ const sshSig = derToSshEcdsa(derSig);
122
+ return Buffer.concat([
123
+ encodeString(key.keyType),
124
+ encodeString(sshSig),
125
+ ]);
126
+ }
127
+ default:
128
+ throw new Error(`Unsupported key type: ${key.keyType}`);
129
+ }
130
+ }
131
+ /**
132
+ * Detect the SSH key type from a Node.js KeyObject.
133
+ */
134
+ function detectKeyType(keyObject) {
135
+ const info = keyObject.asymmetricKeyType;
136
+ if (info === "ed25519")
137
+ return "ed25519";
138
+ if (info === "rsa")
139
+ return "rsa";
140
+ if (info === "ec") {
141
+ // Determine curve from key details
142
+ const details = keyObject.asymmetricKeyDetails;
143
+ switch (details?.namedCurve) {
144
+ case "prime256v1":
145
+ case "P-256":
146
+ return "ecdsa-sha2-nistp256";
147
+ case "secp384r1":
148
+ case "P-384":
149
+ return "ecdsa-sha2-nistp384";
150
+ case "secp521r1":
151
+ case "P-521":
152
+ return "ecdsa-sha2-nistp521";
153
+ default:
154
+ throw new Error(`Unsupported EC curve: ${details?.namedCurve}`);
155
+ }
156
+ }
157
+ throw new Error(`Unsupported key type: ${info}`);
158
+ }
159
+ /**
160
+ * Convert DER-encoded ECDSA signature to SSH mpint format.
161
+ * DER: SEQUENCE { INTEGER r, INTEGER s }
162
+ * SSH: string(r) || string(s)
163
+ */
164
+ function derToSshEcdsa(derSig) {
165
+ // Parse DER SEQUENCE
166
+ let offset = 0;
167
+ if (derSig[offset++] !== 0x30)
168
+ throw new Error("Invalid DER sequence");
169
+ // Skip length byte(s)
170
+ const seqLen = derSig[offset++];
171
+ if (seqLen & 0x80) {
172
+ const lenBytes = seqLen & 0x7f;
173
+ offset += lenBytes;
174
+ }
175
+ // Read r INTEGER
176
+ if (derSig[offset++] !== 0x02)
177
+ throw new Error("Expected INTEGER for r");
178
+ const rLen = derSig[offset++];
179
+ let r = derSig.subarray(offset, offset + rLen);
180
+ offset += rLen;
181
+ // Read s INTEGER
182
+ if (derSig[offset++] !== 0x02)
183
+ throw new Error("Expected INTEGER for s");
184
+ const sLen = derSig[offset++];
185
+ let s = derSig.subarray(offset, offset + sLen);
186
+ // Strip leading zero bytes (DER uses them for positive sign)
187
+ while (r.length > 1 && r[0] === 0)
188
+ r = r.subarray(1);
189
+ while (s.length > 1 && s[0] === 0)
190
+ s = s.subarray(1);
191
+ return Buffer.concat([encodeString(r), encodeString(s)]);
192
+ }
193
+ // Cleanup on process exit
194
+ process.on("exit", () => {
195
+ clearKeys();
196
+ });
197
+ //# sourceMappingURL=ssh-key-agent.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * TOTP code generation — ported from extension/src/lib/totp.ts.
3
+ */
4
+ export interface TOTPParams {
5
+ secret: string;
6
+ algorithm?: string;
7
+ digits?: number;
8
+ period?: number;
9
+ }
10
+ export declare function generateTOTPCode(params: TOTPParams): string;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * TOTP code generation — ported from extension/src/lib/totp.ts.
3
+ */
4
+ import { TOTP, Secret } from "otpauth";
5
+ const ALLOWED_ALGORITHMS = ["SHA1", "SHA256", "SHA512"];
6
+ function validateParams(params) {
7
+ const algo = (params.algorithm ?? "SHA1").toUpperCase();
8
+ if (!ALLOWED_ALGORITHMS.includes(algo)) {
9
+ throw new Error("INVALID_TOTP");
10
+ }
11
+ const digits = params.digits ?? 6;
12
+ if (!Number.isInteger(digits) || digits < 6 || digits > 8) {
13
+ throw new Error("INVALID_TOTP");
14
+ }
15
+ const period = params.period ?? 30;
16
+ if (!Number.isInteger(period) || period < 15 || period > 60) {
17
+ throw new Error("INVALID_TOTP");
18
+ }
19
+ }
20
+ export function generateTOTPCode(params) {
21
+ validateParams(params);
22
+ const algorithm = (params.algorithm ?? "SHA1").toUpperCase();
23
+ const otp = new TOTP({
24
+ secret: Secret.fromBase32(params.secret),
25
+ algorithm,
26
+ digits: params.digits ?? 6,
27
+ period: params.period ?? 30,
28
+ });
29
+ return otp.generate();
30
+ }
31
+ //# sourceMappingURL=totp.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * In-memory vault state.
3
+ *
4
+ * Holds the encryption key while the vault is unlocked.
5
+ * The key exists only in process memory — never persisted to disk.
6
+ */
7
+ export declare function setEncryptionKey(key: CryptoKey, userId?: string): void;
8
+ /** Store the raw secret key bytes for IPC transfer (--eval daemon fork). */
9
+ export declare function setSecretKeyBytes(bytes: Uint8Array): void;
10
+ /** Get raw secret key bytes for IPC transfer. Returns null if not stored. */
11
+ export declare function getSecretKeyBytes(): Uint8Array | null;
12
+ export declare function getUserId(): string | null;
13
+ export declare function getEncryptionKey(): CryptoKey | null;
14
+ export declare function isUnlocked(): boolean;
15
+ export declare function lockVault(): void;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * In-memory vault state.
3
+ *
4
+ * Holds the encryption key while the vault is unlocked.
5
+ * The key exists only in process memory — never persisted to disk.
6
+ */
7
+ let encryptionKey = null;
8
+ let vaultUserId = null;
9
+ let secretKeyBytes = null;
10
+ export function setEncryptionKey(key, userId) {
11
+ encryptionKey = key;
12
+ if (userId)
13
+ vaultUserId = userId;
14
+ }
15
+ /** Store the raw secret key bytes for IPC transfer (--eval daemon fork). */
16
+ export function setSecretKeyBytes(bytes) {
17
+ secretKeyBytes = bytes;
18
+ }
19
+ /** Get raw secret key bytes for IPC transfer. Returns null if not stored. */
20
+ export function getSecretKeyBytes() {
21
+ return secretKeyBytes;
22
+ }
23
+ export function getUserId() {
24
+ return vaultUserId;
25
+ }
26
+ export function getEncryptionKey() {
27
+ return encryptionKey;
28
+ }
29
+ export function isUnlocked() {
30
+ return encryptionKey !== null;
31
+ }
32
+ export function lockVault() {
33
+ encryptionKey = null;
34
+ vaultUserId = null;
35
+ secretKeyBytes = null;
36
+ }
37
+ //# sourceMappingURL=vault-state.js.map
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "passwd-sso-cli",
3
+ "version": "0.4.3",
4
+ "description": "CLI for passwd-sso password manager",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/ngc-shj/passwd-sso.git",
10
+ "directory": "cli"
11
+ },
12
+ "homepage": "https://github.com/ngc-shj/passwd-sso/tree/main/cli",
13
+ "keywords": [
14
+ "password-manager",
15
+ "cli",
16
+ "sso",
17
+ "vault",
18
+ "ssh-agent"
19
+ ],
20
+ "engines": {
21
+ "node": ">=20"
22
+ },
23
+ "bin": {
24
+ "passwd-sso": "./dist/index.js"
25
+ },
26
+ "files": [
27
+ "dist/**/*.js",
28
+ "dist/**/*.d.ts"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "dev": "tsx src/index.ts",
33
+ "prepublishOnly": "tsc",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest"
36
+ },
37
+ "dependencies": {
38
+ "bcrypt-pbkdf": "^1.0.2",
39
+ "chalk": "^5.4.1",
40
+ "cli-table3": "^0.6.5",
41
+ "clipboardy": "^4.0.0",
42
+ "commander": "^13.1.0",
43
+ "inquirer": "^12.6.0",
44
+ "otpauth": "^9.4.0",
45
+ "zod": "^4.3.6"
46
+ },
47
+ "optionalDependencies": {
48
+ "keytar": "^7.9.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.15.3",
52
+ "tsx": "^4.19.4",
53
+ "typescript": "^5.9.0-beta",
54
+ "vitest": "^4.0.18"
55
+ }
56
+ }