vaulter 1.0.29 → 1.0.31

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 (73) hide show
  1. package/dist/cli/commands/init.d.ts +1 -0
  2. package/dist/cli/commands/init.d.ts.map +1 -1
  3. package/dist/cli/commands/init.js +90 -136
  4. package/dist/cli/commands/init.js.map +1 -1
  5. package/dist/cli/commands/key/rotate.d.ts +23 -0
  6. package/dist/cli/commands/key/rotate.d.ts.map +1 -0
  7. package/dist/cli/commands/key/rotate.js +232 -0
  8. package/dist/cli/commands/key/rotate.js.map +1 -0
  9. package/dist/cli/commands/key.d.ts.map +1 -1
  10. package/dist/cli/commands/key.js +6 -226
  11. package/dist/cli/commands/key.js.map +1 -1
  12. package/dist/cli/index.js +7 -1
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/lib/init-generator.d.ts +82 -0
  15. package/dist/lib/init-generator.d.ts.map +1 -0
  16. package/dist/lib/init-generator.js +468 -0
  17. package/dist/lib/init-generator.js.map +1 -0
  18. package/dist/mcp/tools/config.d.ts +122 -0
  19. package/dist/mcp/tools/config.d.ts.map +1 -0
  20. package/dist/mcp/tools/config.js +336 -0
  21. package/dist/mcp/tools/config.js.map +1 -0
  22. package/dist/mcp/tools/definitions.d.ts +11 -0
  23. package/dist/mcp/tools/definitions.d.ts.map +1 -0
  24. package/dist/mcp/tools/definitions.js +469 -0
  25. package/dist/mcp/tools/definitions.js.map +1 -0
  26. package/dist/mcp/tools/handlers/analysis.d.ts +13 -0
  27. package/dist/mcp/tools/handlers/analysis.d.ts.map +1 -0
  28. package/dist/mcp/tools/handlers/analysis.js +192 -0
  29. package/dist/mcp/tools/handlers/analysis.js.map +1 -0
  30. package/dist/mcp/tools/handlers/batch.d.ts +12 -0
  31. package/dist/mcp/tools/handlers/batch.d.ts.map +1 -0
  32. package/dist/mcp/tools/handlers/batch.js +157 -0
  33. package/dist/mcp/tools/handlers/batch.js.map +1 -0
  34. package/dist/mcp/tools/handlers/core.d.ts +14 -0
  35. package/dist/mcp/tools/handlers/core.d.ts.map +1 -0
  36. package/dist/mcp/tools/handlers/core.js +112 -0
  37. package/dist/mcp/tools/handlers/core.js.map +1 -0
  38. package/dist/mcp/tools/handlers/iac.d.ts +17 -0
  39. package/dist/mcp/tools/handlers/iac.d.ts.map +1 -0
  40. package/dist/mcp/tools/handlers/iac.js +122 -0
  41. package/dist/mcp/tools/handlers/iac.js.map +1 -0
  42. package/dist/mcp/tools/handlers/init.d.ts +11 -0
  43. package/dist/mcp/tools/handlers/init.d.ts.map +1 -0
  44. package/dist/mcp/tools/handlers/init.js +86 -0
  45. package/dist/mcp/tools/handlers/init.js.map +1 -0
  46. package/dist/mcp/tools/handlers/k8s.d.ts +11 -0
  47. package/dist/mcp/tools/handlers/k8s.d.ts.map +1 -0
  48. package/dist/mcp/tools/handlers/k8s.js +113 -0
  49. package/dist/mcp/tools/handlers/k8s.js.map +1 -0
  50. package/dist/mcp/tools/handlers/keys.d.ts +28 -0
  51. package/dist/mcp/tools/handlers/keys.d.ts.map +1 -0
  52. package/dist/mcp/tools/handlers/keys.js +384 -0
  53. package/dist/mcp/tools/handlers/keys.js.map +1 -0
  54. package/dist/mcp/tools/handlers/monorepo.d.ts +29 -0
  55. package/dist/mcp/tools/handlers/monorepo.d.ts.map +1 -0
  56. package/dist/mcp/tools/handlers/monorepo.js +323 -0
  57. package/dist/mcp/tools/handlers/monorepo.js.map +1 -0
  58. package/dist/mcp/tools/handlers/sync.d.ts +12 -0
  59. package/dist/mcp/tools/handlers/sync.d.ts.map +1 -0
  60. package/dist/mcp/tools/handlers/sync.js +100 -0
  61. package/dist/mcp/tools/handlers/sync.js.map +1 -0
  62. package/dist/mcp/tools/index.d.ts +15 -0
  63. package/dist/mcp/tools/index.d.ts.map +1 -0
  64. package/dist/mcp/tools/index.js +129 -0
  65. package/dist/mcp/tools/index.js.map +1 -0
  66. package/dist/mcp/tools.d.ts +8 -81
  67. package/dist/mcp/tools.d.ts.map +1 -1
  68. package/dist/mcp/tools.js +18 -2412
  69. package/dist/mcp/tools.js.map +1 -1
  70. package/dist/types.d.ts +1 -0
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/types.js.map +1 -1
  73. package/package.json +1 -1
@@ -2,6 +2,7 @@
2
2
  * Vaulter CLI - Init Command
3
3
  *
4
4
  * Initialize a new .vaulter configuration in the current directory
5
+ * Uses the shared init-generator module.
5
6
  */
6
7
  import type { CLIArgs, VaulterConfig } from '../../types.js';
7
8
  interface InitContext {
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAG5D,UAAU,WAAW;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,OAAO,CAAA;CACpB;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAkKjE"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAW5D,UAAU,WAAW;IACnB,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,OAAO,CAAA;CACpB;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAsHjE"}
@@ -2,166 +2,120 @@
2
2
  * Vaulter CLI - Init Command
3
3
  *
4
4
  * Initialize a new .vaulter configuration in the current directory
5
+ * Uses the shared init-generator module.
5
6
  */
6
- import fs from 'node:fs';
7
- import path from 'node:path';
8
- import { createDefaultConfig, configExists, findConfigDir } from '../../lib/config-loader.js';
7
+ import { configExists, findConfigDir } from '../../lib/config-loader.js';
8
+ import { generateVaulterStructure, detectMonorepo, getDefaultProjectName, DEFAULT_ENVIRONMENTS } from '../../lib/init-generator.js';
9
+ import { c, print, cyan, yellow, dim } from '../lib/colors.js';
9
10
  /**
10
11
  * Run the init command
11
12
  */
12
13
  export async function runInit(context) {
13
14
  const { args, verbose, dryRun, jsonOutput } = context;
14
- const splitMode = args.split || false;
15
- const splitDirectories = {
16
- mode: 'split',
17
- configs: 'deploy/configs',
18
- secrets: 'deploy/secrets'
19
- };
20
15
  // Check if already initialized
21
- if (configExists()) {
16
+ if (configExists() && !args.force) {
22
17
  const existingDir = findConfigDir();
23
- if (!args.force) {
24
- if (jsonOutput) {
25
- console.log(JSON.stringify({ error: 'already_initialized', path: existingDir }));
26
- }
27
- else {
28
- console.error(`Vaulter already initialized at ${existingDir}`);
29
- console.error('Use --force to reinitialize');
30
- }
31
- process.exit(1);
18
+ if (jsonOutput) {
19
+ console.log(JSON.stringify({ error: 'already_initialized', path: existingDir }));
32
20
  }
21
+ else {
22
+ print.error(`Vaulter already initialized at ${existingDir}`);
23
+ console.error(`Use ${c.highlight('--force')} to reinitialize`);
24
+ }
25
+ process.exit(1);
33
26
  }
34
27
  // Determine project name
35
- const projectName = args.project || args.p || path.basename(process.cwd());
36
- // Config directory path
37
- const configDir = path.join(process.cwd(), '.vaulter');
28
+ const projectName = args.project || args.p || getDefaultProjectName();
29
+ // Detect or force monorepo mode
30
+ const monorepoDetection = detectMonorepo();
31
+ const isMonorepo = args.monorepo || monorepoDetection.isMonorepo;
32
+ const servicesPattern = monorepoDetection.servicesPattern;
38
33
  if (verbose) {
39
- console.log(`Initializing vaulter for project: ${projectName}`);
40
- console.log(`Config directory: ${configDir}`);
34
+ console.log(`Project: ${projectName}`);
35
+ console.log(`Mode: ${isMonorepo ? 'monorepo' : 'single-repo'}`);
36
+ if (monorepoDetection.tool) {
37
+ console.log(`Detected: ${monorepoDetection.tool}`);
38
+ }
39
+ }
40
+ // Build options
41
+ const options = {
42
+ projectName,
43
+ isMonorepo,
44
+ environments: DEFAULT_ENVIRONMENTS,
45
+ backend: args.backend || args.b,
46
+ servicesPattern,
47
+ force: args.force || false,
48
+ dryRun
49
+ };
50
+ // Generate structure
51
+ const result = generateVaulterStructure(process.cwd(), options);
52
+ // Output
53
+ if (jsonOutput) {
54
+ console.log(JSON.stringify({
55
+ success: result.success,
56
+ project: result.projectName,
57
+ mode: result.mode,
58
+ detected: monorepoDetection.tool || null,
59
+ files: result.createdFiles,
60
+ dryRun
61
+ }));
62
+ return;
41
63
  }
42
64
  if (dryRun) {
43
- if (jsonOutput) {
44
- console.log(JSON.stringify({
45
- action: 'init',
46
- project: projectName,
47
- configDir,
48
- splitMode,
49
- dryRun: true
50
- }));
51
- }
52
- else {
53
- console.log('Dry run - would create:');
54
- console.log(` ${configDir}/config.yaml`);
55
- if (splitMode) {
56
- console.log(` ${splitDirectories.configs}/`);
57
- console.log(` ${splitDirectories.secrets}/`);
58
- }
59
- else {
60
- console.log(` ${configDir}/environments/`);
61
- }
65
+ print.info('Dry run - would create:');
66
+ for (const file of result.createdFiles) {
67
+ console.log(` ${cyan(file)}`);
62
68
  }
63
69
  return;
64
70
  }
65
- // Create configuration
66
- createDefaultConfig(configDir, projectName, splitMode ? { directories: splitDirectories } : {});
67
- // Create .gitignore for sensitive files
68
- const gitignorePath = path.join(configDir, '.gitignore');
69
- if (!fs.existsSync(gitignorePath)) {
70
- fs.writeFileSync(gitignorePath, `# Vaulter sensitive files
71
- .key
72
- *.key
73
- *.pem
74
- `);
75
- }
76
- // Create placeholder environment files
77
- const environments = ['dev', 'stg', 'prd', 'sbx', 'dr'];
78
- if (splitMode) {
79
- const baseDir = path.dirname(configDir);
80
- const configsDir = path.join(baseDir, splitDirectories.configs);
81
- const secretsDir = path.join(baseDir, splitDirectories.secrets);
82
- if (!fs.existsSync(configsDir)) {
83
- fs.mkdirSync(configsDir, { recursive: true });
84
- }
85
- if (!fs.existsSync(secretsDir)) {
86
- fs.mkdirSync(secretsDir, { recursive: true });
87
- }
88
- const secretsGitignore = path.join(secretsDir, '.gitignore');
89
- if (!fs.existsSync(secretsGitignore)) {
90
- fs.writeFileSync(secretsGitignore, `# Vaulter secrets (do not commit)
91
- *
92
- !.gitignore
93
- `);
94
- }
95
- for (const env of environments) {
96
- const configsFile = path.join(configsDir, `${env}.env`);
97
- if (!fs.existsSync(configsFile)) {
98
- fs.writeFileSync(configsFile, `# ${env.toUpperCase()} Config Variables
99
- # Non-sensitive config values for ${env}
100
- # Example: NODE_ENV=${env}
101
- `);
102
- }
103
- const secretsFile = path.join(secretsDir, `${env}.env`);
104
- if (!fs.existsSync(secretsFile)) {
105
- fs.writeFileSync(secretsFile, `# ${env.toUpperCase()} Secret Variables
106
- # Sensitive values for ${env} (gitignored)
107
- # Example: DATABASE_URL=postgres://localhost/${env}_db
108
- `);
109
- }
71
+ // Success output
72
+ console.log('');
73
+ print.success(`Initialized vaulter for project: ${c.project(result.projectName)}`);
74
+ console.log('');
75
+ if (isMonorepo) {
76
+ if (monorepoDetection.tool) {
77
+ console.log(` ${dim('Detected:')} ${c.value(monorepoDetection.tool)} monorepo`);
110
78
  }
79
+ console.log(` ${dim('Mode:')} monorepo (with services/)`);
111
80
  }
112
81
  else {
113
- const envDir = path.join(configDir, 'environments');
114
- for (const env of environments) {
115
- const envFile = path.join(envDir, `${env}.env`);
116
- if (!fs.existsSync(envFile)) {
117
- fs.writeFileSync(envFile, `# ${env.toUpperCase()} Environment Variables
118
- # Add your ${env} environment variables here
119
- # Example: DATABASE_URL=postgres://localhost/${env}_db
120
- `);
121
- }
122
- }
82
+ console.log(` ${dim('Mode:')} single-repo`);
123
83
  }
124
- if (jsonOutput) {
125
- console.log(JSON.stringify({
126
- success: true,
127
- project: projectName,
128
- configDir,
129
- splitMode,
130
- files: [
131
- 'config.yaml',
132
- '.gitignore',
133
- ...(splitMode
134
- ? [
135
- `${splitDirectories.secrets}/.gitignore`,
136
- ...environments.map(e => `${splitDirectories.configs}/${e}.env`),
137
- ...environments.map(e => `${splitDirectories.secrets}/${e}.env`)
138
- ]
139
- : environments.map(e => `environments/${e}.env`))
140
- ]
141
- }));
84
+ console.log('');
85
+ console.log(`${dim('Created files:')}`);
86
+ for (const file of result.createdFiles.slice(0, 8)) {
87
+ console.log(` ${cyan(file)}`);
88
+ }
89
+ if (result.createdFiles.length > 8) {
90
+ console.log(` ${dim(`... and ${result.createdFiles.length - 8} more`)}`);
91
+ }
92
+ console.log('');
93
+ console.log(`${c.header('Next steps:')}`);
94
+ console.log('');
95
+ if (isMonorepo) {
96
+ console.log(` ${yellow('1.')} Copy and fill local secrets:`);
97
+ console.log(` ${c.command('cp .vaulter/local/shared.env.example .vaulter/local/shared.env')}`);
98
+ console.log('');
99
+ console.log(` ${yellow('2.')} Configure backend in ${cyan('.vaulter/config.yaml')}`);
100
+ console.log('');
101
+ console.log(` ${yellow('3.')} Generate encryption key:`);
102
+ console.log(` ${c.command('vaulter key generate --name master')}`);
103
+ console.log('');
104
+ console.log(` ${yellow('4.')} Run with env vars loaded:`);
105
+ console.log(` ${c.command('vaulter run -s api -- pnpm dev')}`);
142
106
  }
143
107
  else {
144
- console.log(`✓ Initialized vaulter for project: ${projectName}`);
145
- console.log(` Config: ${configDir}/config.yaml`);
146
- if (splitMode) {
147
- console.log(` Configs: ${splitDirectories.configs}/`);
148
- console.log(` Secrets: ${splitDirectories.secrets}/`);
149
- }
150
- else {
151
- console.log(` Environments: ${path.join(configDir, 'environments')}/`);
152
- }
108
+ console.log(` ${yellow('1.')} Copy and fill local secrets:`);
109
+ console.log(` ${c.command('cp .vaulter/local/.env.example .vaulter/local/.env')}`);
153
110
  console.log('');
154
- console.log('Next steps:');
155
- console.log(' 1. Edit .vaulter/config.yaml to configure your backend');
156
- if (splitMode) {
157
- console.log(' 2. Add non-sensitive vars to deploy/configs/*.env');
158
- console.log(' 3. Add secrets to deploy/secrets/*.env');
159
- console.log(' 4. Run "vaulter sync -e dev" to sync with backend');
160
- }
161
- else {
162
- console.log(' 2. Add environment variables to .vaulter/environments/*.env');
163
- console.log(' 3. Run "vaulter sync -e dev" to sync with backend');
164
- }
111
+ console.log(` ${yellow('2.')} Configure backend in ${cyan('.vaulter/config.yaml')}`);
112
+ console.log('');
113
+ console.log(` ${yellow('3.')} Generate encryption key:`);
114
+ console.log(` ${c.command('vaulter key generate --name master')}`);
115
+ console.log('');
116
+ console.log(` ${yellow('4.')} Run with env vars loaded:`);
117
+ console.log(` ${c.command('vaulter run -- pnpm dev')}`);
165
118
  }
119
+ console.log('');
166
120
  }
167
121
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAW7F;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAoB;IAChD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAA;IACrD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAA;IACrC,MAAM,gBAAgB,GAAG;QACvB,IAAI,EAAE,OAAgB;QACtB,OAAO,EAAE,gBAAgB;QACzB,OAAO,EAAE,gBAAgB;KAC1B,CAAA;IAED,+BAA+B;IAC/B,IAAI,YAAY,EAAE,EAAE,CAAC;QACnB,MAAM,WAAW,GAAG,aAAa,EAAE,CAAA;QACnC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;YAClF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,kCAAkC,WAAW,EAAE,CAAC,CAAA;gBAC9D,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;YAC9C,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAE1E,wBAAwB;IACxB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAA;IAEtD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,qCAAqC,WAAW,EAAE,CAAC,CAAA;QAC/D,OAAO,CAAC,GAAG,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAA;IAC/C,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBACzB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,WAAW;gBACpB,SAAS;gBACT,SAAS;gBACT,MAAM,EAAE,IAAI;aACb,CAAC,CAAC,CAAA;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAA;YACtC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,cAAc,CAAC,CAAA;YACzC,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,KAAK,gBAAgB,CAAC,OAAO,GAAG,CAAC,CAAA;gBAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,gBAAgB,CAAC,OAAO,GAAG,CAAC,CAAA;YAC/C,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,gBAAgB,CAAC,CAAA;YAC7C,CAAC;QACH,CAAC;QACD,OAAM;IACR,CAAC;IAED,uBAAuB;IACvB,mBAAmB,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAE/F,wCAAwC;IACxC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;IACxD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE;;;;CAInC,CAAC,CAAA;IACA,CAAC;IAED,uCAAuC;IACvC,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;IAEvD,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;QAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;QAE/D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC/C,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC/C,CAAC;QAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;QAC5D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACrC,EAAE,CAAC,aAAa,CAAC,gBAAgB,EAAE;;;CAGxC,CAAC,CAAA;QACE,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,GAAG,MAAM,CAAC,CAAA;YACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChC,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE;oCACxB,GAAG;sBACjB,GAAG;CACxB,CAAC,CAAA;YACI,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,GAAG,MAAM,CAAC,CAAA;YACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChC,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE;yBACnC,GAAG;+CACmB,GAAG;CACjD,CAAC,CAAA;YACI,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;QAEnD,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,CAAC,CAAA;YAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE;aAC3C,GAAG;+CAC+B,GAAG;CACjD,CAAC,CAAA;YACI,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;YACzB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,WAAW;YACpB,SAAS;YACT,SAAS;YACT,KAAK,EAAE;gBACL,aAAa;gBACb,YAAY;gBACZ,GAAG,CAAC,SAAS;oBACX,CAAC,CAAC;wBACE,GAAG,gBAAgB,CAAC,OAAO,aAAa;wBACxC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC;wBAChE,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC;qBACjE;oBACH,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;aACpD;SACF,CAAC,CAAC,CAAA;IACL,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,sCAAsC,WAAW,EAAE,CAAC,CAAA;QAChE,OAAO,CAAC,GAAG,CAAC,aAAa,SAAS,cAAc,CAAC,CAAA;QACjD,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,cAAc,gBAAgB,CAAC,OAAO,GAAG,CAAC,CAAA;YACtD,OAAO,CAAC,GAAG,CAAC,cAAc,gBAAgB,CAAC,OAAO,GAAG,CAAC,CAAA;QACxD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,GAAG,CAAC,CAAA;QACzE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACf,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;QAC1B,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAA;QACvE,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAA;YAClE,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAA;YACvD,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAA;QACpE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAA;YAC5E,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAA;QACpE,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Vaulter CLI - Key Rotate Subcommand
3
+ *
4
+ * Handles encryption key rotation:
5
+ * - Exports all variables (decrypted)
6
+ * - Generates new key
7
+ * - Re-encrypts all variables with new key
8
+ * - Creates backup of old key
9
+ */
10
+ import type { VaulterConfig, CLIArgs } from '../../../types.js';
11
+ export interface KeyRotateContext {
12
+ args: CLIArgs;
13
+ config: VaulterConfig | null;
14
+ verbose: boolean;
15
+ dryRun: boolean;
16
+ jsonOutput: boolean;
17
+ getProjectName: () => string;
18
+ }
19
+ /**
20
+ * Run key rotate subcommand
21
+ */
22
+ export declare function runKeyRotate(context: KeyRotateContext): Promise<void>;
23
+ //# sourceMappingURL=rotate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotate.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/key/rotate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAoC,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAWjG,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,EAAE,MAAM,MAAM,CAAA;CAC7B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmP3E"}
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Vaulter CLI - Key Rotate Subcommand
3
+ *
4
+ * Handles encryption key rotation:
5
+ * - Exports all variables (decrypted)
6
+ * - Generates new key
7
+ * - Re-encrypts all variables with new key
8
+ * - Creates backup of old key
9
+ */
10
+ import fs from 'node:fs';
11
+ import path from 'node:path';
12
+ import { generateKeyPair, generatePassphrase } from '../../../lib/crypto.js';
13
+ import { getProjectKeysDir, resolveKeyPath, resolveKeyPaths, getValidEnvironments } from '../../../lib/config-loader.js';
14
+ import { createClientFromConfig } from '../../lib/create-client.js';
15
+ import { createConnectedAuditLogger, disconnectAuditLogger } from '../../lib/audit-helper.js';
16
+ /**
17
+ * Run key rotate subcommand
18
+ */
19
+ export async function runKeyRotate(context) {
20
+ const { args, config, verbose, dryRun, jsonOutput, getProjectName } = context;
21
+ if (!config) {
22
+ console.error('Error: No vaulter configuration found');
23
+ console.error('Run "vaulter init" first');
24
+ process.exit(1);
25
+ }
26
+ const project = getProjectName();
27
+ const service = args.service || args.s || config?.service;
28
+ const environments = getValidEnvironments(config);
29
+ // Validate key configuration
30
+ const keyName = args.name || args.n || config?.encryption?.asymmetric?.key_name || 'master';
31
+ const keysDir = getProjectKeysDir(project);
32
+ if (!jsonOutput && verbose) {
33
+ console.error(`Key rotation for project: ${project}`);
34
+ console.error(`Key name: ${keyName}`);
35
+ console.error(`Environments: ${environments.join(', ')}`);
36
+ }
37
+ // Step 1: Export all variables from all environments
38
+ if (!jsonOutput) {
39
+ console.log('Step 1: Exporting all variables (decrypted)...');
40
+ }
41
+ const exportedData = new Map();
42
+ const client = await createClientFromConfig({ args, config, project, verbose });
43
+ try {
44
+ await client.connect();
45
+ for (const env of environments) {
46
+ const vars = await client.export(project, env, service);
47
+ const varCount = Object.keys(vars).length;
48
+ if (varCount > 0) {
49
+ exportedData.set(env, vars);
50
+ if (!jsonOutput && verbose) {
51
+ console.error(` [${env}] Exported ${varCount} variables`);
52
+ }
53
+ }
54
+ }
55
+ }
56
+ finally {
57
+ await client.disconnect();
58
+ }
59
+ const totalVars = Array.from(exportedData.values()).reduce((sum, vars) => sum + Object.keys(vars).length, 0);
60
+ if (totalVars === 0) {
61
+ if (jsonOutput) {
62
+ console.log(JSON.stringify({
63
+ success: true,
64
+ message: 'No variables to rotate',
65
+ rotated: 0
66
+ }));
67
+ }
68
+ else {
69
+ console.log('No variables found to rotate.');
70
+ }
71
+ return;
72
+ }
73
+ if (!jsonOutput) {
74
+ console.log(` Found ${totalVars} variables across ${exportedData.size} environments`);
75
+ }
76
+ // Step 2: Generate new key
77
+ if (!jsonOutput) {
78
+ console.log('');
79
+ console.log('Step 2: Generating new encryption key...');
80
+ }
81
+ const isAsymmetric = config?.encryption?.mode === 'asymmetric';
82
+ const algorithm = config?.encryption?.asymmetric?.algorithm || 'rsa-4096';
83
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
84
+ let oldKeyBackupPath;
85
+ if (isAsymmetric) {
86
+ // Asymmetric key rotation
87
+ const { privateKey: privateKeyPath, publicKey: publicKeyPath } = resolveKeyPaths(keyName, project);
88
+ if (!fs.existsSync(privateKeyPath)) {
89
+ console.error(`Error: Private key not found: ${privateKeyPath}`);
90
+ process.exit(1);
91
+ }
92
+ oldKeyBackupPath = path.join(keysDir, `${keyName}-backup-${timestamp}`);
93
+ if (!dryRun) {
94
+ // Backup old keys
95
+ fs.mkdirSync(oldKeyBackupPath, { recursive: true });
96
+ fs.copyFileSync(privateKeyPath, path.join(oldKeyBackupPath, `${keyName}.key`));
97
+ fs.copyFileSync(publicKeyPath, path.join(oldKeyBackupPath, `${keyName}.pub`));
98
+ // Generate new key pair
99
+ const { publicKey, privateKey } = generateKeyPair(algorithm);
100
+ fs.writeFileSync(privateKeyPath, privateKey, { mode: 0o600 });
101
+ fs.writeFileSync(publicKeyPath, publicKey);
102
+ if (!jsonOutput && verbose) {
103
+ console.error(` Old keys backed up to: ${oldKeyBackupPath}`);
104
+ console.error(` New keys generated: ${keyName}`);
105
+ }
106
+ }
107
+ }
108
+ else {
109
+ // Symmetric key rotation - use the key file path directly
110
+ const keyFilePath = resolveKeyPath(keyName, project, false);
111
+ oldKeyBackupPath = path.join(keysDir, `${keyName}-backup-${timestamp}.key`);
112
+ if (!dryRun) {
113
+ // Backup old key if exists
114
+ if (fs.existsSync(keyFilePath)) {
115
+ fs.copyFileSync(keyFilePath, oldKeyBackupPath);
116
+ }
117
+ // Generate new passphrase
118
+ const newPassphrase = generatePassphrase();
119
+ fs.mkdirSync(path.dirname(keyFilePath), { recursive: true });
120
+ fs.writeFileSync(keyFilePath, newPassphrase, { mode: 0o600 });
121
+ if (!jsonOutput && verbose) {
122
+ console.error(` Old key backed up to: ${oldKeyBackupPath}`);
123
+ console.error(` New key generated: ${keyFilePath}`);
124
+ }
125
+ }
126
+ }
127
+ if (!jsonOutput) {
128
+ console.log(' New key generated successfully');
129
+ }
130
+ // Step 3: Re-import all variables with new key
131
+ if (!jsonOutput) {
132
+ console.log('');
133
+ console.log('Step 3: Re-encrypting all variables with new key...');
134
+ }
135
+ if (dryRun) {
136
+ if (jsonOutput) {
137
+ console.log(JSON.stringify({
138
+ dryRun: true,
139
+ project,
140
+ keyName,
141
+ environments: Array.from(exportedData.keys()),
142
+ totalVariables: totalVars,
143
+ message: 'Would rotate key and re-encrypt all variables'
144
+ }));
145
+ }
146
+ else {
147
+ console.log('');
148
+ console.log('Dry run - changes that would be made:');
149
+ for (const [env, vars] of exportedData) {
150
+ console.log(` [${env}] Re-encrypt ${Object.keys(vars).length} variables`);
151
+ }
152
+ console.log('');
153
+ console.log('Run without --dry-run to perform the rotation.');
154
+ }
155
+ return;
156
+ }
157
+ // Create new client with new key for re-import
158
+ const newClient = await createClientFromConfig({ args, config, project, verbose });
159
+ const auditLogger = await createConnectedAuditLogger(config, verbose);
160
+ try {
161
+ await newClient.connect();
162
+ let rotatedCount = 0;
163
+ for (const [env, vars] of exportedData) {
164
+ for (const [key, value] of Object.entries(vars)) {
165
+ await newClient.set({
166
+ key,
167
+ value,
168
+ project,
169
+ service,
170
+ environment: env,
171
+ metadata: {
172
+ source: 'rotation',
173
+ rotatedAt: new Date().toISOString()
174
+ }
175
+ });
176
+ rotatedCount++;
177
+ }
178
+ if (!jsonOutput && verbose) {
179
+ console.error(` [${env}] Re-encrypted ${Object.keys(vars).length} variables`);
180
+ }
181
+ }
182
+ // Log rotation to audit
183
+ if (auditLogger) {
184
+ try {
185
+ await auditLogger.log({
186
+ operation: 'rotate',
187
+ key: '*',
188
+ project,
189
+ environment: 'all',
190
+ service,
191
+ source: 'cli',
192
+ metadata: {
193
+ keyName,
194
+ keyType: isAsymmetric ? 'asymmetric' : 'symmetric',
195
+ environments: Array.from(exportedData.keys()),
196
+ variablesRotated: rotatedCount,
197
+ backupPath: oldKeyBackupPath
198
+ }
199
+ });
200
+ }
201
+ catch {
202
+ // Ignore audit errors
203
+ }
204
+ }
205
+ if (jsonOutput) {
206
+ console.log(JSON.stringify({
207
+ success: true,
208
+ project,
209
+ keyName,
210
+ keyType: isAsymmetric ? 'asymmetric' : 'symmetric',
211
+ environments: Array.from(exportedData.keys()),
212
+ rotated: rotatedCount,
213
+ backupPath: oldKeyBackupPath
214
+ }));
215
+ }
216
+ else {
217
+ console.log('');
218
+ console.log(`✓ Key rotation complete`);
219
+ console.log(` Variables re-encrypted: ${rotatedCount}`);
220
+ console.log(` Environments: ${Array.from(exportedData.keys()).join(', ')}`);
221
+ console.log(` Old key backup: ${oldKeyBackupPath}`);
222
+ console.log('');
223
+ console.log('Important: The old key backup should be securely deleted after');
224
+ console.log('verifying the rotation was successful.');
225
+ }
226
+ }
227
+ finally {
228
+ await newClient.disconnect();
229
+ await disconnectAuditLogger(auditLogger);
230
+ }
231
+ }
232
+ //# sourceMappingURL=rotate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotate.js","sourceRoot":"","sources":["../../../../src/cli/commands/key/rotate.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAoC,MAAM,gBAAgB,CAAA;AAc9F,UAAU,UAAU;IAClB,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,OAAO,CAAA;CACpB;AASD;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC/D"}
1
+ {"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAoC,MAAM,gBAAgB,CAAA;AAe9F,UAAU,UAAU;IAClB,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,OAAO,CAAA;CACpB;AASD;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAuC/D"}