@snapback/cli 1.1.14 → 1.6.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 (45) hide show
  1. package/dist/SkippedTestDetector-5WJZKZQ3.js +5 -0
  2. package/dist/{SkippedTestDetector-B3JZUE5G.js.map → SkippedTestDetector-5WJZKZQ3.js.map} +1 -1
  3. package/dist/{analysis-C6XVLBAL.js → analysis-YI4UNUCM.js} +6 -6
  4. package/dist/{analysis-C6XVLBAL.js.map → analysis-YI4UNUCM.js.map} +1 -1
  5. package/dist/{chunk-Q5XZ3DCB.js → chunk-7JX6Y4TL.js} +135 -15
  6. package/dist/chunk-7JX6Y4TL.js.map +1 -0
  7. package/dist/{chunk-OJNDAPC2.js → chunk-ARVV3F4K.js} +5 -5
  8. package/dist/{chunk-OJNDAPC2.js.map → chunk-ARVV3F4K.js.map} +1 -1
  9. package/dist/{chunk-A3TUM7U4.js → chunk-EU2IZPOK.js} +4 -4
  10. package/dist/{chunk-A3TUM7U4.js.map → chunk-EU2IZPOK.js.map} +1 -1
  11. package/dist/{chunk-QAKFE3NE.js → chunk-FVIYXFCL.js} +4 -4
  12. package/dist/{chunk-QAKFE3NE.js.map → chunk-FVIYXFCL.js.map} +1 -1
  13. package/dist/{chunk-2TOJVUVJ.js → chunk-R7CUQ7CU.js} +4 -4
  14. package/dist/{chunk-2TOJVUVJ.js.map → chunk-R7CUQ7CU.js.map} +1 -1
  15. package/dist/{chunk-BW7RALUZ.js → chunk-RB7H4UQJ.js} +3 -3
  16. package/dist/{chunk-BW7RALUZ.js.map → chunk-RB7H4UQJ.js.map} +1 -1
  17. package/dist/{chunk-5EQLSU5B.js → chunk-SOABQWAU.js} +5 -5
  18. package/dist/{chunk-5EQLSU5B.js.map → chunk-SOABQWAU.js.map} +1 -1
  19. package/dist/{dist-RPM72FHJ.js → dist-O6EBXLN6.js} +5 -5
  20. package/dist/{dist-D2SHOZMS.js.map → dist-O6EBXLN6.js.map} +1 -1
  21. package/dist/{dist-L76VXYJ5.js → dist-PJVBBZTF.js} +5 -5
  22. package/dist/{dist-L76VXYJ5.js.map → dist-PJVBBZTF.js.map} +1 -1
  23. package/dist/index.js +7737 -7966
  24. package/dist/index.js.map +1 -1
  25. package/dist/learning-pruner-QC4CTJDX.js +5 -0
  26. package/dist/{learning-pruner-YSZSOOOC.js.map → learning-pruner-QC4CTJDX.js.map} +1 -1
  27. package/dist/{secure-credentials-A4QHHOE2.js → secure-credentials-IWQB6KU4.js} +4 -4
  28. package/dist/{secure-credentials-A4QHHOE2.js.map → secure-credentials-IWQB6KU4.js.map} +1 -1
  29. package/dist/snapback-dir-V6MWXIW4.js +5 -0
  30. package/dist/{snapback-dir-6QUSO6Y3.js.map → snapback-dir-V6MWXIW4.js.map} +1 -1
  31. package/package.json +6 -40
  32. package/dist/SkippedTestDetector-B3JZUE5G.js +0 -5
  33. package/dist/chunk-6MR2TINI.js +0 -27
  34. package/dist/chunk-6MR2TINI.js.map +0 -1
  35. package/dist/chunk-LEXNOXPV.js +0 -21621
  36. package/dist/chunk-LEXNOXPV.js.map +0 -1
  37. package/dist/chunk-Q5XZ3DCB.js.map +0 -1
  38. package/dist/chunk-QLCHTUT5.js +0 -1067
  39. package/dist/chunk-QLCHTUT5.js.map +0 -1
  40. package/dist/dist-D2SHOZMS.js +0 -8
  41. package/dist/dist-RPM72FHJ.js.map +0 -1
  42. package/dist/learning-pruner-YSZSOOOC.js +0 -7
  43. package/dist/snapback-dir-6QUSO6Y3.js +0 -6
  44. package/dist/storage-H366UNAR.js +0 -6
  45. package/dist/storage-H366UNAR.js.map +0 -1
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node --no-warnings=ExperimentalWarning
2
+ export { AutomatedLearningPruner } from './chunk-SOABQWAU.js';
3
+ import './chunk-RB7H4UQJ.js';
4
+ //# sourceMappingURL=learning-pruner-QC4CTJDX.js.map
5
+ //# sourceMappingURL=learning-pruner-QC4CTJDX.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"learning-pruner-YSZSOOOC.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"learning-pruner-QC4CTJDX.js"}
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env node
2
- import { __name } from './chunk-BW7RALUZ.js';
1
+ #!/usr/bin/env node --no-warnings=ExperimentalWarning
2
+ import { __name } from './chunk-RB7H4UQJ.js';
3
3
  import { scryptSync, randomBytes, createCipheriv, createDecipheriv } from 'crypto';
4
4
  import { unlink, readFile, mkdir, writeFile } from 'fs/promises';
5
5
  import { homedir, hostname, platform, userInfo } from 'os';
@@ -262,5 +262,5 @@ async function isLoggedInSecure() {
262
262
  __name(isLoggedInSecure, "isLoggedInSecure");
263
263
 
264
264
  export { SecureCredentialsManager, clearCredentialsSecure, getCredentialsSecure, getSecureCredentials, isLoggedInSecure, saveCredentialsSecure };
265
- //# sourceMappingURL=secure-credentials-A4QHHOE2.js.map
266
- //# sourceMappingURL=secure-credentials-A4QHHOE2.js.map
265
+ //# sourceMappingURL=secure-credentials-IWQB6KU4.js.map
266
+ //# sourceMappingURL=secure-credentials-IWQB6KU4.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/secure-credentials.ts"],"names":["SERVICE_NAME","ACCOUNT_NAME","ENCRYPTION_ALGORITHM","KEY_LENGTH","IV_LENGTH","AUTH_TAG_LENGTH","SALT_LENGTH","GLOBAL_DIR","join","homedir","CREDENTIALS_FILE","ENCRYPTED_CREDENTIALS_FILE","createKeytarProvider","keytar","name","isAvailable","getPassword","service","account","setPassword","password","deletePassword","deriveMachineKey","salt","machineData","hostname","platform","userInfo","username","process","arch","scryptSync","encryptCredentials","credentials","key","iv","randomBytes","cipher","createCipheriv","plaintext","JSON","stringify","encrypted","Buffer","concat","update","final","authTag","getAuthTag","decryptCredentials","data","subarray","decipher","createDecipheriv","setAuthTag","decrypted","parse","toString","createEncryptedFileProvider","_service","_account","readFile","mkdir","dirname","recursive","writeFile","unlink","SecureCredentialsManager","provider","initialized","initialize","keytarProvider","getProviderName","getCredentials","stored","legacy","getLegacyCredentials","setCredentials","content","Error","clearCredentials","isLoggedIn","accessToken","expiresAt","Date","secureCredentialsManager","getSecureCredentials","getCredentialsSecure","saveCredentialsSecure","clearCredentialsSecure","isLoggedInSecure"],"mappings":"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","file":"secure-credentials-A4QHHOE2.js","sourcesContent":["/**\n * Secure Credentials Storage for SnapBack CLI\n *\n * FIX 4: Implements OS keychain storage with file fallback\n *\n * Security Hierarchy:\n * 1. OS Keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service)\n * 2. Encrypted file fallback (AES-256-GCM with machine-derived key)\n * 3. Plain text fallback (development only, with warning)\n *\n * @module services/secure-credentials\n */\n\nimport { createCipheriv, createDecipheriv, randomBytes, scryptSync } from \"node:crypto\";\nimport { mkdir, readFile, unlink, writeFile } from \"node:fs/promises\";\nimport { homedir, hostname, platform, userInfo } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { GlobalCredentials } from \"./snapback-dir\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\nconst SERVICE_NAME = \"snapback-cli\";\nconst ACCOUNT_NAME = \"default\";\nconst ENCRYPTION_ALGORITHM = \"aes-256-gcm\";\nconst KEY_LENGTH = 32;\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\nconst SALT_LENGTH = 32;\n\n// File paths\nconst GLOBAL_DIR = join(homedir(), \".snapback\");\nconst CREDENTIALS_FILE = join(GLOBAL_DIR, \"credentials.json\");\nconst ENCRYPTED_CREDENTIALS_FILE = join(GLOBAL_DIR, \"credentials.enc\");\n\n// =============================================================================\n// KEYCHAIN INTERFACE\n// =============================================================================\n\n/**\n * Keychain abstraction interface\n * Allows for different implementations based on availability\n */\ninterface KeychainProvider {\n\tname: string;\n\tisAvailable(): Promise<boolean>;\n\tgetPassword(service: string, account: string): Promise<string | null>;\n\tsetPassword(service: string, account: string, password: string): Promise<void>;\n\tdeletePassword(service: string, account: string): Promise<boolean>;\n}\n\n// =============================================================================\n// KEYTAR PROVIDER (OS KEYCHAIN)\n// =============================================================================\n\n/**\n * Keytar-based keychain provider\n * Uses OS-level secure credential storage\n */\nasync function createKeytarProvider(): Promise<KeychainProvider | null> {\n\ttry {\n\t\t// Dynamic import to handle missing keytar gracefully\n\t\t// @ts-expect-error - keytar is optional dependency\n\t\tconst keytar = await import(\"keytar\");\n\n\t\treturn {\n\t\t\tname: \"keytar\",\n\t\t\tasync isAvailable(): Promise<boolean> {\n\t\t\t\ttry {\n\t\t\t\t\t// Test availability by trying a no-op operation\n\t\t\t\t\tawait keytar.getPassword(\"__snapback_test__\", \"__test__\");\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tasync getPassword(service: string, account: string): Promise<string | null> {\n\t\t\t\treturn keytar.getPassword(service, account);\n\t\t\t},\n\t\t\tasync setPassword(service: string, account: string, password: string): Promise<void> {\n\t\t\t\tawait keytar.setPassword(service, account, password);\n\t\t\t},\n\t\t\tasync deletePassword(service: string, account: string): Promise<boolean> {\n\t\t\t\treturn keytar.deletePassword(service, account);\n\t\t\t},\n\t\t};\n\t} catch {\n\t\t// keytar not available (not installed or native module issues)\n\t\treturn null;\n\t}\n}\n\n// =============================================================================\n// ENCRYPTED FILE PROVIDER\n// =============================================================================\n\n/**\n * Derive an encryption key from machine-specific data\n * This provides defense-in-depth even if the file is copied to another machine\n */\nfunction deriveMachineKey(salt: Buffer): Buffer {\n\t// Combine machine-specific values for key derivation\n\tconst machineData = [\n\t\thostname(),\n\t\tplatform(),\n\t\tuserInfo().username,\n\t\thomedir(),\n\t\t// Add some entropy from process info\n\t\tprocess.arch,\n\t\tprocess.platform,\n\t].join(\"|\");\n\n\treturn scryptSync(machineData, salt, KEY_LENGTH);\n}\n\n/**\n * Encrypt credentials with machine-derived key\n */\nfunction encryptCredentials(credentials: GlobalCredentials, salt: Buffer): Buffer {\n\tconst key = deriveMachineKey(salt);\n\tconst iv = randomBytes(IV_LENGTH);\n\tconst cipher = createCipheriv(ENCRYPTION_ALGORITHM, key, iv);\n\n\tconst plaintext = JSON.stringify(credentials);\n\tconst encrypted = Buffer.concat([cipher.update(plaintext, \"utf8\"), cipher.final()]);\n\tconst authTag = cipher.getAuthTag();\n\n\t// Format: salt (32) + iv (12) + authTag (16) + encrypted data\n\treturn Buffer.concat([salt, iv, authTag, encrypted]);\n}\n\n/**\n * Decrypt credentials with machine-derived key\n */\nfunction decryptCredentials(data: Buffer): GlobalCredentials {\n\t// Extract components\n\tconst salt = data.subarray(0, SALT_LENGTH);\n\tconst iv = data.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);\n\tconst authTag = data.subarray(SALT_LENGTH + IV_LENGTH, SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH);\n\tconst encrypted = data.subarray(SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH);\n\n\tconst key = deriveMachineKey(salt);\n\tconst decipher = createDecipheriv(ENCRYPTION_ALGORITHM, key, iv);\n\tdecipher.setAuthTag(authTag);\n\n\tconst decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);\n\treturn JSON.parse(decrypted.toString(\"utf8\")) as GlobalCredentials;\n}\n\n/**\n * Encrypted file provider\n * Uses AES-256-GCM with machine-derived key\n */\nfunction createEncryptedFileProvider(): KeychainProvider {\n\treturn {\n\t\tname: \"encrypted-file\",\n\t\tasync isAvailable(): Promise<boolean> {\n\t\t\treturn true; // Always available as fallback\n\t\t},\n\t\tasync getPassword(_service: string, _account: string): Promise<string | null> {\n\t\t\ttry {\n\t\t\t\tconst data = await readFile(ENCRYPTED_CREDENTIALS_FILE);\n\t\t\t\tconst credentials = decryptCredentials(data);\n\t\t\t\treturn JSON.stringify(credentials);\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\tasync setPassword(_service: string, _account: string, password: string): Promise<void> {\n\t\t\tconst credentials = JSON.parse(password) as GlobalCredentials;\n\t\t\tconst salt = randomBytes(SALT_LENGTH);\n\t\t\tconst encrypted = encryptCredentials(credentials, salt);\n\n\t\t\tawait mkdir(dirname(ENCRYPTED_CREDENTIALS_FILE), { recursive: true });\n\t\t\tawait writeFile(ENCRYPTED_CREDENTIALS_FILE, encrypted);\n\t\t},\n\t\tasync deletePassword(_service: string, _account: string): Promise<boolean> {\n\t\t\ttry {\n\t\t\t\tawait unlink(ENCRYPTED_CREDENTIALS_FILE);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// =============================================================================\n// PLAIN FILE PROVIDER (DEVELOPMENT FALLBACK)\n// =============================================================================\n\n/**\n * Plain file provider (legacy, development only)\n * Shows warning when used in production\n * @deprecated Use encrypted file provider instead\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction _createPlainFileProvider(): KeychainProvider {\n\tlet warningShown = false;\n\n\treturn {\n\t\tname: \"plain-file\",\n\t\tasync isAvailable(): Promise<boolean> {\n\t\t\treturn true;\n\t\t},\n\t\tasync getPassword(_service: string, _account: string): Promise<string | null> {\n\t\t\ttry {\n\t\t\t\tconst content = await readFile(CREDENTIALS_FILE, \"utf8\");\n\t\t\t\treturn content;\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\tasync setPassword(_service: string, _account: string, password: string): Promise<void> {\n\t\t\tif (process.env.NODE_ENV === \"production\" && !warningShown) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"\\n⚠️ Warning: Storing credentials in plain text. \" +\n\t\t\t\t\t\t\"Install 'keytar' for OS keychain support: pnpm add keytar\\n\",\n\t\t\t\t);\n\t\t\t\twarningShown = true;\n\t\t\t}\n\n\t\t\tawait mkdir(dirname(CREDENTIALS_FILE), { recursive: true });\n\t\t\tawait writeFile(CREDENTIALS_FILE, password, { mode: 0o600 }); // Restrict file permissions\n\t\t},\n\t\tasync deletePassword(_service: string, _account: string): Promise<boolean> {\n\t\t\ttry {\n\t\t\t\tawait unlink(CREDENTIALS_FILE);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// =============================================================================\n// SECURE CREDENTIALS MANAGER\n// =============================================================================\n\n/**\n * Secure Credentials Manager\n *\n * Automatically selects the most secure available storage:\n * 1. OS Keychain (via keytar)\n * 2. Encrypted file\n * 3. Plain file (with warning)\n */\nclass SecureCredentialsManager {\n\tprivate provider: KeychainProvider | null = null;\n\tprivate initialized = false;\n\n\t/**\n\t * Initialize the credentials manager\n\t * Selects the best available provider\n\t */\n\tasync initialize(): Promise<void> {\n\t\tif (this.initialized) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Try keytar first (OS keychain)\n\t\tconst keytarProvider = await createKeytarProvider();\n\t\tif (keytarProvider && (await keytarProvider.isAvailable())) {\n\t\t\tthis.provider = keytarProvider;\n\t\t\tthis.initialized = true;\n\t\t\treturn;\n\t\t}\n\n\t\t// Fall back to encrypted file\n\t\tthis.provider = createEncryptedFileProvider();\n\t\tthis.initialized = true;\n\t}\n\n\t/**\n\t * Get the name of the active provider\n\t */\n\tgetProviderName(): string {\n\t\treturn this.provider?.name ?? \"none\";\n\t}\n\n\t/**\n\t * Get stored credentials\n\t */\n\tasync getCredentials(): Promise<GlobalCredentials | null> {\n\t\tawait this.initialize();\n\t\tif (!this.provider) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst stored = await this.provider.getPassword(SERVICE_NAME, ACCOUNT_NAME);\n\t\tif (!stored) {\n\t\t\t// Check legacy plain file as migration fallback\n\t\t\tconst legacy = await this.getLegacyCredentials();\n\t\t\tif (legacy) {\n\t\t\t\t// Migrate to secure storage\n\t\t\t\tawait this.setCredentials(legacy);\n\t\t\t\t// Delete legacy file after successful migration\n\t\t\t\ttry {\n\t\t\t\t\tawait unlink(CREDENTIALS_FILE);\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore if file doesn't exist\n\t\t\t\t}\n\t\t\t\treturn legacy;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\treturn JSON.parse(stored) as GlobalCredentials;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get legacy plain-text credentials for migration\n\t */\n\tprivate async getLegacyCredentials(): Promise<GlobalCredentials | null> {\n\t\ttry {\n\t\t\tconst content = await readFile(CREDENTIALS_FILE, \"utf8\");\n\t\t\treturn JSON.parse(content) as GlobalCredentials;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Save credentials securely\n\t */\n\tasync setCredentials(credentials: GlobalCredentials): Promise<void> {\n\t\tawait this.initialize();\n\t\tif (!this.provider) {\n\t\t\tthrow new Error(\"No credentials provider available\");\n\t\t}\n\n\t\tawait this.provider.setPassword(SERVICE_NAME, ACCOUNT_NAME, JSON.stringify(credentials));\n\t}\n\n\t/**\n\t * Clear stored credentials\n\t */\n\tasync clearCredentials(): Promise<void> {\n\t\tawait this.initialize();\n\t\tif (!this.provider) {\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.provider.deletePassword(SERVICE_NAME, ACCOUNT_NAME);\n\n\t\t// Also clean up any legacy files\n\t\ttry {\n\t\t\tawait unlink(CREDENTIALS_FILE);\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait unlink(ENCRYPTED_CREDENTIALS_FILE);\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t}\n\n\t/**\n\t * Check if user is logged in\n\t */\n\tasync isLoggedIn(): Promise<boolean> {\n\t\tconst credentials = await this.getCredentials();\n\t\tif (!credentials?.accessToken) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if token is expired\n\t\tif (credentials.expiresAt) {\n\t\t\tconst expiresAt = new Date(credentials.expiresAt);\n\t\t\tif (expiresAt < new Date()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n}\n\n// =============================================================================\n// EXPORTS\n// =============================================================================\n\n// Singleton instance\nlet secureCredentialsManager: SecureCredentialsManager | null = null;\n\n/**\n * Get the secure credentials manager singleton\n */\nexport function getSecureCredentials(): SecureCredentialsManager {\n\tif (!secureCredentialsManager) {\n\t\tsecureCredentialsManager = new SecureCredentialsManager();\n\t}\n\treturn secureCredentialsManager;\n}\n\n/**\n * Secure versions of credential functions (drop-in replacements)\n */\nexport async function getCredentialsSecure(): Promise<GlobalCredentials | null> {\n\treturn getSecureCredentials().getCredentials();\n}\n\nexport async function saveCredentialsSecure(credentials: GlobalCredentials): Promise<void> {\n\treturn getSecureCredentials().setCredentials(credentials);\n}\n\nexport async function clearCredentialsSecure(): Promise<void> {\n\treturn getSecureCredentials().clearCredentials();\n}\n\nexport async function isLoggedInSecure(): Promise<boolean> {\n\treturn getSecureCredentials().isLoggedIn();\n}\n\nexport { SecureCredentialsManager };\n"]}
1
+ {"version":3,"sources":["../src/services/secure-credentials.ts"],"names":["SERVICE_NAME","ACCOUNT_NAME","ENCRYPTION_ALGORITHM","KEY_LENGTH","IV_LENGTH","AUTH_TAG_LENGTH","SALT_LENGTH","GLOBAL_DIR","join","homedir","CREDENTIALS_FILE","ENCRYPTED_CREDENTIALS_FILE","createKeytarProvider","keytar","name","isAvailable","getPassword","service","account","setPassword","password","deletePassword","deriveMachineKey","salt","machineData","hostname","platform","userInfo","username","process","arch","scryptSync","encryptCredentials","credentials","key","iv","randomBytes","cipher","createCipheriv","plaintext","JSON","stringify","encrypted","Buffer","concat","update","final","authTag","getAuthTag","decryptCredentials","data","subarray","decipher","createDecipheriv","setAuthTag","decrypted","parse","toString","createEncryptedFileProvider","_service","_account","readFile","mkdir","dirname","recursive","writeFile","unlink","SecureCredentialsManager","provider","initialized","initialize","keytarProvider","getProviderName","getCredentials","stored","legacy","getLegacyCredentials","setCredentials","content","Error","clearCredentials","isLoggedIn","accessToken","expiresAt","Date","secureCredentialsManager","getSecureCredentials","getCredentialsSecure","saveCredentialsSecure","clearCredentialsSecure","isLoggedInSecure"],"mappings":"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","file":"secure-credentials-IWQB6KU4.js","sourcesContent":["/**\n * Secure Credentials Storage for SnapBack CLI\n *\n * FIX 4: Implements OS keychain storage with file fallback\n *\n * Security Hierarchy:\n * 1. OS Keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service)\n * 2. Encrypted file fallback (AES-256-GCM with machine-derived key)\n * 3. Plain text fallback (development only, with warning)\n *\n * @module services/secure-credentials\n */\n\nimport { createCipheriv, createDecipheriv, randomBytes, scryptSync } from \"node:crypto\";\nimport { mkdir, readFile, unlink, writeFile } from \"node:fs/promises\";\nimport { homedir, hostname, platform, userInfo } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { GlobalCredentials } from \"./snapback-dir\";\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\nconst SERVICE_NAME = \"snapback-cli\";\nconst ACCOUNT_NAME = \"default\";\nconst ENCRYPTION_ALGORITHM = \"aes-256-gcm\";\nconst KEY_LENGTH = 32;\nconst IV_LENGTH = 12;\nconst AUTH_TAG_LENGTH = 16;\nconst SALT_LENGTH = 32;\n\n// File paths\nconst GLOBAL_DIR = join(homedir(), \".snapback\");\nconst CREDENTIALS_FILE = join(GLOBAL_DIR, \"credentials.json\");\nconst ENCRYPTED_CREDENTIALS_FILE = join(GLOBAL_DIR, \"credentials.enc\");\n\n// =============================================================================\n// KEYCHAIN INTERFACE\n// =============================================================================\n\n/**\n * Keychain abstraction interface\n * Allows for different implementations based on availability\n */\ninterface KeychainProvider {\n\tname: string;\n\tisAvailable(): Promise<boolean>;\n\tgetPassword(service: string, account: string): Promise<string | null>;\n\tsetPassword(service: string, account: string, password: string): Promise<void>;\n\tdeletePassword(service: string, account: string): Promise<boolean>;\n}\n\n// =============================================================================\n// KEYTAR PROVIDER (OS KEYCHAIN)\n// =============================================================================\n\n/**\n * Keytar-based keychain provider\n * Uses OS-level secure credential storage\n */\nasync function createKeytarProvider(): Promise<KeychainProvider | null> {\n\ttry {\n\t\t// Dynamic import to handle missing keytar gracefully\n\t\t// @ts-expect-error - keytar is optional dependency\n\t\tconst keytar = await import(\"keytar\");\n\n\t\treturn {\n\t\t\tname: \"keytar\",\n\t\t\tasync isAvailable(): Promise<boolean> {\n\t\t\t\ttry {\n\t\t\t\t\t// Test availability by trying a no-op operation\n\t\t\t\t\tawait keytar.getPassword(\"__snapback_test__\", \"__test__\");\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tasync getPassword(service: string, account: string): Promise<string | null> {\n\t\t\t\treturn keytar.getPassword(service, account);\n\t\t\t},\n\t\t\tasync setPassword(service: string, account: string, password: string): Promise<void> {\n\t\t\t\tawait keytar.setPassword(service, account, password);\n\t\t\t},\n\t\t\tasync deletePassword(service: string, account: string): Promise<boolean> {\n\t\t\t\treturn keytar.deletePassword(service, account);\n\t\t\t},\n\t\t};\n\t} catch {\n\t\t// keytar not available (not installed or native module issues)\n\t\treturn null;\n\t}\n}\n\n// =============================================================================\n// ENCRYPTED FILE PROVIDER\n// =============================================================================\n\n/**\n * Derive an encryption key from machine-specific data\n * This provides defense-in-depth even if the file is copied to another machine\n */\nfunction deriveMachineKey(salt: Buffer): Buffer {\n\t// Combine machine-specific values for key derivation\n\tconst machineData = [\n\t\thostname(),\n\t\tplatform(),\n\t\tuserInfo().username,\n\t\thomedir(),\n\t\t// Add some entropy from process info\n\t\tprocess.arch,\n\t\tprocess.platform,\n\t].join(\"|\");\n\n\treturn scryptSync(machineData, salt, KEY_LENGTH);\n}\n\n/**\n * Encrypt credentials with machine-derived key\n */\nfunction encryptCredentials(credentials: GlobalCredentials, salt: Buffer): Buffer {\n\tconst key = deriveMachineKey(salt);\n\tconst iv = randomBytes(IV_LENGTH);\n\tconst cipher = createCipheriv(ENCRYPTION_ALGORITHM, key, iv);\n\n\tconst plaintext = JSON.stringify(credentials);\n\tconst encrypted = Buffer.concat([cipher.update(plaintext, \"utf8\"), cipher.final()]);\n\tconst authTag = cipher.getAuthTag();\n\n\t// Format: salt (32) + iv (12) + authTag (16) + encrypted data\n\treturn Buffer.concat([salt, iv, authTag, encrypted]);\n}\n\n/**\n * Decrypt credentials with machine-derived key\n */\nfunction decryptCredentials(data: Buffer): GlobalCredentials {\n\t// Extract components\n\tconst salt = data.subarray(0, SALT_LENGTH);\n\tconst iv = data.subarray(SALT_LENGTH, SALT_LENGTH + IV_LENGTH);\n\tconst authTag = data.subarray(SALT_LENGTH + IV_LENGTH, SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH);\n\tconst encrypted = data.subarray(SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH);\n\n\tconst key = deriveMachineKey(salt);\n\tconst decipher = createDecipheriv(ENCRYPTION_ALGORITHM, key, iv);\n\tdecipher.setAuthTag(authTag);\n\n\tconst decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);\n\treturn JSON.parse(decrypted.toString(\"utf8\")) as GlobalCredentials;\n}\n\n/**\n * Encrypted file provider\n * Uses AES-256-GCM with machine-derived key\n */\nfunction createEncryptedFileProvider(): KeychainProvider {\n\treturn {\n\t\tname: \"encrypted-file\",\n\t\tasync isAvailable(): Promise<boolean> {\n\t\t\treturn true; // Always available as fallback\n\t\t},\n\t\tasync getPassword(_service: string, _account: string): Promise<string | null> {\n\t\t\ttry {\n\t\t\t\tconst data = await readFile(ENCRYPTED_CREDENTIALS_FILE);\n\t\t\t\tconst credentials = decryptCredentials(data);\n\t\t\t\treturn JSON.stringify(credentials);\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\tasync setPassword(_service: string, _account: string, password: string): Promise<void> {\n\t\t\tconst credentials = JSON.parse(password) as GlobalCredentials;\n\t\t\tconst salt = randomBytes(SALT_LENGTH);\n\t\t\tconst encrypted = encryptCredentials(credentials, salt);\n\n\t\t\tawait mkdir(dirname(ENCRYPTED_CREDENTIALS_FILE), { recursive: true });\n\t\t\tawait writeFile(ENCRYPTED_CREDENTIALS_FILE, encrypted);\n\t\t},\n\t\tasync deletePassword(_service: string, _account: string): Promise<boolean> {\n\t\t\ttry {\n\t\t\t\tawait unlink(ENCRYPTED_CREDENTIALS_FILE);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// =============================================================================\n// PLAIN FILE PROVIDER (DEVELOPMENT FALLBACK)\n// =============================================================================\n\n/**\n * Plain file provider (legacy, development only)\n * Shows warning when used in production\n * @deprecated Use encrypted file provider instead\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction _createPlainFileProvider(): KeychainProvider {\n\tlet warningShown = false;\n\n\treturn {\n\t\tname: \"plain-file\",\n\t\tasync isAvailable(): Promise<boolean> {\n\t\t\treturn true;\n\t\t},\n\t\tasync getPassword(_service: string, _account: string): Promise<string | null> {\n\t\t\ttry {\n\t\t\t\tconst content = await readFile(CREDENTIALS_FILE, \"utf8\");\n\t\t\t\treturn content;\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\tasync setPassword(_service: string, _account: string, password: string): Promise<void> {\n\t\t\tif (process.env.NODE_ENV === \"production\" && !warningShown) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t\"\\n⚠️ Warning: Storing credentials in plain text. \" +\n\t\t\t\t\t\t\"Install 'keytar' for OS keychain support: pnpm add keytar\\n\",\n\t\t\t\t);\n\t\t\t\twarningShown = true;\n\t\t\t}\n\n\t\t\tawait mkdir(dirname(CREDENTIALS_FILE), { recursive: true });\n\t\t\tawait writeFile(CREDENTIALS_FILE, password, { mode: 0o600 }); // Restrict file permissions\n\t\t},\n\t\tasync deletePassword(_service: string, _account: string): Promise<boolean> {\n\t\t\ttry {\n\t\t\t\tawait unlink(CREDENTIALS_FILE);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// =============================================================================\n// SECURE CREDENTIALS MANAGER\n// =============================================================================\n\n/**\n * Secure Credentials Manager\n *\n * Automatically selects the most secure available storage:\n * 1. OS Keychain (via keytar)\n * 2. Encrypted file\n * 3. Plain file (with warning)\n */\nclass SecureCredentialsManager {\n\tprivate provider: KeychainProvider | null = null;\n\tprivate initialized = false;\n\n\t/**\n\t * Initialize the credentials manager\n\t * Selects the best available provider\n\t */\n\tasync initialize(): Promise<void> {\n\t\tif (this.initialized) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Try keytar first (OS keychain)\n\t\tconst keytarProvider = await createKeytarProvider();\n\t\tif (keytarProvider && (await keytarProvider.isAvailable())) {\n\t\t\tthis.provider = keytarProvider;\n\t\t\tthis.initialized = true;\n\t\t\treturn;\n\t\t}\n\n\t\t// Fall back to encrypted file\n\t\tthis.provider = createEncryptedFileProvider();\n\t\tthis.initialized = true;\n\t}\n\n\t/**\n\t * Get the name of the active provider\n\t */\n\tgetProviderName(): string {\n\t\treturn this.provider?.name ?? \"none\";\n\t}\n\n\t/**\n\t * Get stored credentials\n\t */\n\tasync getCredentials(): Promise<GlobalCredentials | null> {\n\t\tawait this.initialize();\n\t\tif (!this.provider) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst stored = await this.provider.getPassword(SERVICE_NAME, ACCOUNT_NAME);\n\t\tif (!stored) {\n\t\t\t// Check legacy plain file as migration fallback\n\t\t\tconst legacy = await this.getLegacyCredentials();\n\t\t\tif (legacy) {\n\t\t\t\t// Migrate to secure storage\n\t\t\t\tawait this.setCredentials(legacy);\n\t\t\t\t// Delete legacy file after successful migration\n\t\t\t\ttry {\n\t\t\t\t\tawait unlink(CREDENTIALS_FILE);\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore if file doesn't exist\n\t\t\t\t}\n\t\t\t\treturn legacy;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\treturn JSON.parse(stored) as GlobalCredentials;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Get legacy plain-text credentials for migration\n\t */\n\tprivate async getLegacyCredentials(): Promise<GlobalCredentials | null> {\n\t\ttry {\n\t\t\tconst content = await readFile(CREDENTIALS_FILE, \"utf8\");\n\t\t\treturn JSON.parse(content) as GlobalCredentials;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Save credentials securely\n\t */\n\tasync setCredentials(credentials: GlobalCredentials): Promise<void> {\n\t\tawait this.initialize();\n\t\tif (!this.provider) {\n\t\t\tthrow new Error(\"No credentials provider available\");\n\t\t}\n\n\t\tawait this.provider.setPassword(SERVICE_NAME, ACCOUNT_NAME, JSON.stringify(credentials));\n\t}\n\n\t/**\n\t * Clear stored credentials\n\t */\n\tasync clearCredentials(): Promise<void> {\n\t\tawait this.initialize();\n\t\tif (!this.provider) {\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.provider.deletePassword(SERVICE_NAME, ACCOUNT_NAME);\n\n\t\t// Also clean up any legacy files\n\t\ttry {\n\t\t\tawait unlink(CREDENTIALS_FILE);\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t\ttry {\n\t\t\tawait unlink(ENCRYPTED_CREDENTIALS_FILE);\n\t\t} catch {\n\t\t\t// Ignore\n\t\t}\n\t}\n\n\t/**\n\t * Check if user is logged in\n\t */\n\tasync isLoggedIn(): Promise<boolean> {\n\t\tconst credentials = await this.getCredentials();\n\t\tif (!credentials?.accessToken) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check if token is expired\n\t\tif (credentials.expiresAt) {\n\t\t\tconst expiresAt = new Date(credentials.expiresAt);\n\t\t\tif (expiresAt < new Date()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n}\n\n// =============================================================================\n// EXPORTS\n// =============================================================================\n\n// Singleton instance\nlet secureCredentialsManager: SecureCredentialsManager | null = null;\n\n/**\n * Get the secure credentials manager singleton\n */\nexport function getSecureCredentials(): SecureCredentialsManager {\n\tif (!secureCredentialsManager) {\n\t\tsecureCredentialsManager = new SecureCredentialsManager();\n\t}\n\treturn secureCredentialsManager;\n}\n\n/**\n * Secure versions of credential functions (drop-in replacements)\n */\nexport async function getCredentialsSecure(): Promise<GlobalCredentials | null> {\n\treturn getSecureCredentials().getCredentials();\n}\n\nexport async function saveCredentialsSecure(credentials: GlobalCredentials): Promise<void> {\n\treturn getSecureCredentials().setCredentials(credentials);\n}\n\nexport async function clearCredentialsSecure(): Promise<void> {\n\treturn getSecureCredentials().clearCredentials();\n}\n\nexport async function isLoggedInSecure(): Promise<boolean> {\n\treturn getSecureCredentials().isLoggedIn();\n}\n\nexport { SecureCredentialsManager };\n"]}
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node --no-warnings=ExperimentalWarning
2
+ export { GlobalConfigSchema, GlobalCredentialsSchema, LearningEntrySchema, ProtectedFileSchema, SessionStateSchema, ViolationEntrySchema, WorkspaceConfigSchema, WorkspaceVitalsSchema, appendSnapbackJsonl, clearCredentials, createGlobalDirectory, createSnapbackDirectory, deleteGlobalJson, endCurrentSession, findWorkspaceRoot, generateId, getCredentials, getCurrentSession, getGlobalConfig, getGlobalDir, getGlobalPath, getLearnings, getProtectedFiles, getStats, getViolations, getWorkspaceConfig, getWorkspaceDir, getWorkspacePath, getWorkspaceVitals, isLoggedIn, isSnapbackInitialized, loadSnapbackJsonl, pathExists, readGlobalJson, readSnapbackJson, recordLearning, recordViolation, saveCredentials, saveCurrentSession, saveGlobalConfig, saveProtectedFiles, saveWorkspaceConfig, saveWorkspaceVitals, writeGlobalJson, writeSnapbackJson } from './chunk-7JX6Y4TL.js';
3
+ import './chunk-RB7H4UQJ.js';
4
+ //# sourceMappingURL=snapback-dir-V6MWXIW4.js.map
5
+ //# sourceMappingURL=snapback-dir-V6MWXIW4.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"snapback-dir-6QUSO6Y3.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"snapback-dir-V6MWXIW4.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapback/cli",
3
- "version": "1.1.14",
3
+ "version": "1.6.0",
4
4
  "description": "CLI tool for managing SnapBack snapshots and file protection",
5
5
  "homepage": "https://snapback.dev",
6
6
  "repository": {
@@ -33,63 +33,30 @@
33
33
  "LICENSE"
34
34
  ],
35
35
  "dependencies": {
36
- "@asteasolutions/zod-to-openapi": "7.3.4",
37
- "@aws-sdk/client-s3": "3.750.0",
38
- "@aws-sdk/s3-request-presigner": "3.750.0",
39
- "@babel/parser": "7.28.5",
40
- "@babel/traverse": "7.28.5",
41
36
  "@inquirer/prompts": "7.9.0",
42
- "@modelcontextprotocol/sdk": "1.25.3",
43
- "@typescript-eslint/parser": "8.46.2",
44
- "@xenova/transformers": "^2.17.2",
45
- "atomically": "^2.0.0",
46
- "better-sqlite3": "9.6.0",
47
- "bottleneck": "2.19.5",
48
37
  "boxen": "8.0.1",
49
38
  "chalk": "4.1.2",
50
39
  "chokidar": "4.0.3",
51
40
  "cli-table3": "0.6.5",
52
41
  "commander": "9.5.0",
53
42
  "conf": "13.0.1",
54
- "cosmiconfig": "8.3.6",
55
- "dotenv": "17.2.2",
56
- "drizzle-orm": "0.44.5",
57
- "es-toolkit": "1.39.10",
58
- "esprima": "4.0.1",
59
- "eventemitter2": "6.4.9",
60
43
  "execa": "9.5.2",
61
- "fast-glob": "3.3.3",
62
- "ky": "1.7.2",
63
- "listr2": "8.2.5",
64
44
  "log-update": "6.1.0",
65
- "lru-cache": "10.4.3",
66
- "madge": "8.0.0",
67
- "minimatch": "10.0.1",
68
- "nanoid": "5.1.5",
69
- "opossum": "9.0.0",
70
45
  "ora": "5.4.1",
71
- "p-limit": "3.1.0",
72
- "p-retry": "6.2.0",
73
- "pino": "9.5.0",
74
- "quick-lru": "7.0.0",
75
- "simple-git": "3.28.0",
76
- "sqlite-vec": "0.1.7-alpha.2",
77
- "yargs": "17.7.2",
78
46
  "zod": "3.25.76"
79
47
  },
80
48
  "devDependencies": {
81
49
  "@vitest/coverage-v8": "3.2.4",
82
50
  "tsup": "8.5.0",
83
- "tsx": "4.20.5",
84
51
  "typescript": "5.9.2",
85
52
  "vitest": "3.2.4",
86
- "@snapback/intelligence": "0.1.0",
87
- "@snapback/sdk": "0.2.0",
88
53
  "@snapback/contracts": "0.2.1",
89
- "@snapback/mcp": "0.1.0",
54
+ "@snapback/core": "0.2.0",
90
55
  "@snapback/engine": "0.1.0",
56
+ "@snapback/intelligence": "0.1.0",
57
+ "@snapback/mcp": "0.1.0",
91
58
  "@snapback/mcp-config": "1.0.0",
92
- "@snapback/core": "0.2.0"
59
+ "@snapback/sdk": "0.2.0"
93
60
  },
94
61
  "publishConfig": {
95
62
  "access": "public",
@@ -101,12 +68,11 @@
101
68
  },
102
69
  "type": "module",
103
70
  "engines": {
104
- "node": ">=18.17.0",
71
+ "node": ">=22.5.0",
105
72
  "npm": ">=8.0.0",
106
73
  "pnpm": ">=8.0.0"
107
74
  },
108
75
  "scripts": {
109
- "postinstall": "node scripts/postinstall.mjs",
110
76
  "build": "tsup && tsc --build tsconfig.build.json --emitDeclarationOnly",
111
77
  "check": "biome check .",
112
78
  "dev": "tsup --watch",
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- export { analyzeSkippedTests, detectSkippedTests, getSkippedTestSummary } from './chunk-QAKFE3NE.js';
3
- import './chunk-BW7RALUZ.js';
4
- //# sourceMappingURL=SkippedTestDetector-B3JZUE5G.js.map
5
- //# sourceMappingURL=SkippedTestDetector-B3JZUE5G.js.map
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env node
2
- import { __name } from './chunk-BW7RALUZ.js';
3
- import { nanoid } from 'nanoid';
4
-
5
- function generateId(prefix) {
6
- const id = nanoid();
7
- return prefix ? `${prefix}-${id}` : id;
8
- }
9
- __name(generateId, "generateId");
10
- function slugify(description, maxLength = 30) {
11
- return description.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, maxLength);
12
- }
13
- __name(slugify, "slugify");
14
- function generateSnapshotId(description) {
15
- if (description && description.length > 0) {
16
- const slug = slugify(description);
17
- if (slug.length > 0) {
18
- return `snapshot-${slug}-${Date.now()}-${nanoid(9)}`;
19
- }
20
- }
21
- return `snapshot-${Date.now()}-${nanoid(9)}`;
22
- }
23
- __name(generateSnapshotId, "generateSnapshotId");
24
-
25
- export { generateId, generateSnapshotId };
26
- //# sourceMappingURL=chunk-6MR2TINI.js.map
27
- //# sourceMappingURL=chunk-6MR2TINI.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../packages/contracts/dist/id-generator.js"],"names":["generateId","prefix","id","nanoid","slugify","description","maxLength","toLowerCase","trim","replace","slice","generateSnapshotId","length","slug","Date","now"],"mappings":";;;;AAMO,SAASA,WAAWC,MAAAA,EAAM;AAC7B,EAAA,MAAMC,KAAKC,MAAAA,EAAAA;AACX,EAAA,OAAOF,MAAAA,GAAS,CAAA,EAAGA,MAAAA,CAAAA,CAAAA,EAAUC,EAAAA,CAAAA,CAAAA,GAAOA,EAAAA;AACxC;AAHgBF,MAAAA,CAAAA,UAAAA,EAAAA,YAAAA,CAAAA;AAQhB,SAASI,OAAAA,CAAQC,WAAAA,EAAaC,SAAAA,GAAY,EAAA,EAAE;AACxC,EAAA,OAAOD,WAAAA,CACFE,aAAW,CACXC,IAAAA,GACAC,OAAAA,CAAQ,eAAA,EAAiB,EAAA,CAAA,CACzBA,OAAAA,CAAQ,MAAA,EAAQ,GAAA,CAAA,CAChBA,OAAAA,CAAQ,KAAA,EAAO,GAAA,CAAA,CACfA,OAAAA,CAAQ,UAAU,EAAA,CAAA,CAClBC,KAAAA,CAAM,CAAA,EAAGJ,SAAAA,CAAAA;AAClB;AATSF,MAAAA,CAAAA,OAAAA,EAAAA,SAAAA,CAAAA;AAiBF,SAASO,mBAAmBN,WAAAA,EAAW;AAC1C,EAAA,IAAIA,WAAAA,IAAeA,WAAAA,CAAYO,MAAAA,GAAS,CAAA,EAAG;AACvC,IAAA,MAAMC,IAAAA,GAAOT,QAAQC,WAAAA,CAAAA;AACrB,IAAA,IAAIQ,IAAAA,CAAKD,SAAS,CAAA,EAAG;AACjB,MAAA,OAAO,CAAA,SAAA,EAAYC,IAAAA,CAAAA,CAAAA,EAAQC,IAAAA,CAAKC,KAAG,CAAA,CAAA,EAAMZ,MAAAA,CAAO,CAAA,CAAA,CAAA,CAAA;AACpD,IAAA;AACJ,EAAA;AACA,EAAA,OAAO,YAAYW,IAAAA,CAAKC,GAAAA,EAAG,CAAA,CAAA,EAAMZ,MAAAA,CAAO,CAAA,CAAA,CAAA,CAAA;AAC5C;AARgBQ,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA","file":"chunk-6MR2TINI.js","sourcesContent":["import { nanoid } from \"nanoid\";\n/**\n * Generate a unique ID with optional prefix\n * @param prefix Optional prefix for the ID (e.g., 'user', 'session')\n * @returns Unique ID string\n */\nexport function generateId(prefix) {\n const id = nanoid();\n return prefix ? `${prefix}-${id}` : id;\n}\n/**\n * Slugify a description for use in snapshot IDs\n * Converts \"Before fixing auth flow\" to \"before-fixing-auth-flow\"\n */\nfunction slugify(description, maxLength = 30) {\n return description\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s-]/g, \"\") // Remove non-alphanumeric\n .replace(/\\s+/g, \"-\") // Spaces to hyphens\n .replace(/-+/g, \"-\") // Collapse hyphens\n .replace(/^-|-$/g, \"\") // Trim hyphens\n .slice(0, maxLength);\n}\n/**\n * Generate a snapshot ID in the standard format\n * Format with description: snapshot-<slug>-<timestamp>-<random>\n * Format without: snapshot-<timestamp>-<random>\n * @param description Optional human-readable description\n * @returns Snapshot ID string\n */\nexport function generateSnapshotId(description) {\n if (description && description.length > 0) {\n const slug = slugify(description);\n if (slug.length > 0) {\n return `snapshot-${slug}-${Date.now()}-${nanoid(9)}`;\n }\n }\n return `snapshot-${Date.now()}-${nanoid(9)}`;\n}\n"]}