@fractary/core 0.4.0 → 0.5.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.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @fractary/core - Secrets Sanitization Tests
3
+ *
4
+ * Comprehensive unit tests for the secrets sanitization utilities.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=secrets.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.test.d.ts","sourceRoot":"","sources":["../../../src/common/__tests__/secrets.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,320 @@
1
+ "use strict";
2
+ /**
3
+ * @fractary/core - Secrets Sanitization Tests
4
+ *
5
+ * Comprehensive unit tests for the secrets sanitization utilities.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ const secrets_1 = require("../secrets");
9
+ describe('sanitizeSecrets', () => {
10
+ describe('GitHub tokens', () => {
11
+ it('should redact GitHub personal access tokens (ghp_)', () => {
12
+ const input = 'Token: ghp_1234567890abcdefghijklmnopqrstuvwxyz12';
13
+ const result = (0, secrets_1.sanitizeSecrets)(input);
14
+ expect(result).toBe('Token: [REDACTED_GITHUB_TOKEN]');
15
+ });
16
+ it('should redact GitHub OAuth tokens (gho_)', () => {
17
+ const input = 'Auth: gho_1234567890abcdefghijklmnopqrstuvwxyz12';
18
+ const result = (0, secrets_1.sanitizeSecrets)(input);
19
+ expect(result).toBe('Auth: [REDACTED_GITHUB_TOKEN]');
20
+ });
21
+ it('should redact GitHub user-to-server tokens (ghu_)', () => {
22
+ const input = 'ghu_abcdefghijklmnopqrstuvwxyz1234567890ab';
23
+ const result = (0, secrets_1.sanitizeSecrets)(input);
24
+ expect(result).toBe('[REDACTED_GITHUB_TOKEN]');
25
+ });
26
+ it('should redact GitHub server-to-server tokens (ghs_)', () => {
27
+ const input = 'ghs_abcdefghijklmnopqrstuvwxyz1234567890ab';
28
+ const result = (0, secrets_1.sanitizeSecrets)(input);
29
+ expect(result).toBe('[REDACTED_GITHUB_TOKEN]');
30
+ });
31
+ it('should redact GitHub refresh tokens (ghr_)', () => {
32
+ const input = 'ghr_abcdefghijklmnopqrstuvwxyz1234567890ab';
33
+ const result = (0, secrets_1.sanitizeSecrets)(input);
34
+ expect(result).toBe('[REDACTED_GITHUB_TOKEN]');
35
+ });
36
+ it('should redact multiple GitHub tokens in one string', () => {
37
+ const input = 'Token1: ghp_abc123456789012345678901234567890123 and Token2: gho_xyz123456789012345678901234567890123';
38
+ const result = (0, secrets_1.sanitizeSecrets)(input);
39
+ expect(result).toBe('Token1: [REDACTED_GITHUB_TOKEN] and Token2: [REDACTED_GITHUB_TOKEN]');
40
+ });
41
+ });
42
+ describe('GitLab tokens', () => {
43
+ it('should redact GitLab personal access tokens', () => {
44
+ const input = 'token: glpat-xxxxxxxxxxxxxxxxxxxx';
45
+ const result = (0, secrets_1.sanitizeSecrets)(input);
46
+ expect(result).toBe('token: [REDACTED]');
47
+ });
48
+ it('should redact GitLab tokens with hyphens and underscores', () => {
49
+ const input = 'glpat-abc_def-123_456_789_012_345';
50
+ const result = (0, secrets_1.sanitizeSecrets)(input);
51
+ expect(result).toBe('[REDACTED_GITLAB_TOKEN]');
52
+ });
53
+ });
54
+ describe('Bearer tokens', () => {
55
+ it('should redact Bearer tokens', () => {
56
+ const input = 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0';
57
+ const result = (0, secrets_1.sanitizeSecrets)(input);
58
+ expect(result).toBe('Authorization: Bearer [REDACTED]');
59
+ });
60
+ it('should redact Bearer tokens with padding', () => {
61
+ const input = 'Bearer abc123==';
62
+ const result = (0, secrets_1.sanitizeSecrets)(input);
63
+ expect(result).toBe('Bearer [REDACTED]');
64
+ });
65
+ });
66
+ describe('Basic auth', () => {
67
+ it('should redact Basic auth tokens', () => {
68
+ const input = 'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=';
69
+ const result = (0, secrets_1.sanitizeSecrets)(input);
70
+ expect(result).toBe('Authorization: Basic [REDACTED]');
71
+ });
72
+ });
73
+ describe('key-value patterns', () => {
74
+ it('should redact token in JSON format', () => {
75
+ const input = '{"token": "secret123"}';
76
+ const result = (0, secrets_1.sanitizeSecrets)(input);
77
+ expect(result).toContain('[REDACTED]');
78
+ });
79
+ it('should redact password in config', () => {
80
+ const input = 'password: mysecretpassword';
81
+ const result = (0, secrets_1.sanitizeSecrets)(input);
82
+ expect(result).toBe('password: [REDACTED]');
83
+ });
84
+ it('should redact api_key values', () => {
85
+ const input = 'api_key=sk-1234567890abcdefghij';
86
+ const result = (0, secrets_1.sanitizeSecrets)(input);
87
+ expect(result).toBe('api_key: [REDACTED]');
88
+ });
89
+ it('should redact secret values', () => {
90
+ const input = 'secret: "my_super_secret_value"';
91
+ const result = (0, secrets_1.sanitizeSecrets)(input);
92
+ expect(result).toBe('secret: [REDACTED]');
93
+ });
94
+ it('should redact access_token values', () => {
95
+ const input = 'access_token=abcdef123456';
96
+ const result = (0, secrets_1.sanitizeSecrets)(input);
97
+ expect(result).toBe('access_token: [REDACTED]');
98
+ });
99
+ });
100
+ describe('edge cases', () => {
101
+ it('should handle empty string', () => {
102
+ expect((0, secrets_1.sanitizeSecrets)('')).toBe('');
103
+ });
104
+ it('should handle string with no secrets', () => {
105
+ const input = 'This is a normal message with no secrets';
106
+ expect((0, secrets_1.sanitizeSecrets)(input)).toBe(input);
107
+ });
108
+ it('should handle very long strings', () => {
109
+ const longString = 'a'.repeat(10000) + 'ghp_' + 'b'.repeat(36) + 'c'.repeat(10000);
110
+ const result = (0, secrets_1.sanitizeSecrets)(longString);
111
+ expect(result).toContain('[REDACTED_GITHUB_TOKEN]');
112
+ expect(result).not.toContain('ghp_');
113
+ });
114
+ it('should handle strings with special characters', () => {
115
+ const input = 'token: ghp_abc123!@#$%^&*()_+-=[]{}|;:,.<>?';
116
+ const result = (0, secrets_1.sanitizeSecrets)(input);
117
+ expect(result).toContain('[REDACTED]');
118
+ });
119
+ });
120
+ });
121
+ describe('containsSecrets', () => {
122
+ it('should detect token keyword', () => {
123
+ expect((0, secrets_1.containsSecrets)('my token is here')).toBe(true);
124
+ });
125
+ it('should detect password keyword', () => {
126
+ expect((0, secrets_1.containsSecrets)('enter your password')).toBe(true);
127
+ });
128
+ it('should detect secret keyword', () => {
129
+ expect((0, secrets_1.containsSecrets)('this is a secret')).toBe(true);
130
+ });
131
+ it('should detect api_key keyword', () => {
132
+ expect((0, secrets_1.containsSecrets)('set your api_key')).toBe(true);
133
+ });
134
+ it('should detect api-key keyword', () => {
135
+ expect((0, secrets_1.containsSecrets)('set your api-key')).toBe(true);
136
+ });
137
+ it('should detect bearer keyword', () => {
138
+ expect((0, secrets_1.containsSecrets)('Bearer token required')).toBe(true);
139
+ });
140
+ it('should detect authorization keyword', () => {
141
+ expect((0, secrets_1.containsSecrets)('Authorization header')).toBe(true);
142
+ });
143
+ it('should detect GitHub token prefix', () => {
144
+ expect((0, secrets_1.containsSecrets)('ghp_token')).toBe(true);
145
+ expect((0, secrets_1.containsSecrets)('gho_token')).toBe(true);
146
+ });
147
+ it('should detect GitLab token prefix', () => {
148
+ expect((0, secrets_1.containsSecrets)('glpat-token')).toBe(true);
149
+ });
150
+ it('should return false for normal text', () => {
151
+ expect((0, secrets_1.containsSecrets)('hello world')).toBe(false);
152
+ expect((0, secrets_1.containsSecrets)('this is normal text')).toBe(false);
153
+ });
154
+ it('should be case insensitive', () => {
155
+ expect((0, secrets_1.containsSecrets)('TOKEN')).toBe(true);
156
+ expect((0, secrets_1.containsSecrets)('Password')).toBe(true);
157
+ expect((0, secrets_1.containsSecrets)('SECRET')).toBe(true);
158
+ });
159
+ });
160
+ describe('isSensitiveKey', () => {
161
+ it('should identify token keys', () => {
162
+ expect((0, secrets_1.isSensitiveKey)('token')).toBe(true);
163
+ expect((0, secrets_1.isSensitiveKey)('access_token')).toBe(true);
164
+ expect((0, secrets_1.isSensitiveKey)('refresh_token')).toBe(true);
165
+ expect((0, secrets_1.isSensitiveKey)('GITHUB_TOKEN')).toBe(true);
166
+ });
167
+ it('should identify key keys', () => {
168
+ expect((0, secrets_1.isSensitiveKey)('api_key')).toBe(true);
169
+ expect((0, secrets_1.isSensitiveKey)('apiKey')).toBe(true);
170
+ expect((0, secrets_1.isSensitiveKey)('private_key')).toBe(true);
171
+ });
172
+ it('should identify secret keys', () => {
173
+ expect((0, secrets_1.isSensitiveKey)('secret')).toBe(true);
174
+ expect((0, secrets_1.isSensitiveKey)('client_secret')).toBe(true);
175
+ expect((0, secrets_1.isSensitiveKey)('SECRET_KEY')).toBe(true);
176
+ });
177
+ it('should identify password keys', () => {
178
+ expect((0, secrets_1.isSensitiveKey)('password')).toBe(true);
179
+ expect((0, secrets_1.isSensitiveKey)('db_password')).toBe(true);
180
+ expect((0, secrets_1.isSensitiveKey)('PASSWORD')).toBe(true);
181
+ });
182
+ it('should identify auth keys', () => {
183
+ expect((0, secrets_1.isSensitiveKey)('auth')).toBe(true);
184
+ expect((0, secrets_1.isSensitiveKey)('authorization')).toBe(true);
185
+ expect((0, secrets_1.isSensitiveKey)('auth_token')).toBe(true);
186
+ });
187
+ it('should return false for non-sensitive keys', () => {
188
+ expect((0, secrets_1.isSensitiveKey)('name')).toBe(false);
189
+ expect((0, secrets_1.isSensitiveKey)('email')).toBe(false);
190
+ expect((0, secrets_1.isSensitiveKey)('description')).toBe(false);
191
+ expect((0, secrets_1.isSensitiveKey)('owner')).toBe(false);
192
+ });
193
+ it('should be case insensitive', () => {
194
+ expect((0, secrets_1.isSensitiveKey)('TOKEN')).toBe(true);
195
+ expect((0, secrets_1.isSensitiveKey)('Token')).toBe(true);
196
+ expect((0, secrets_1.isSensitiveKey)('tOkEn')).toBe(true);
197
+ });
198
+ });
199
+ describe('redactConfig', () => {
200
+ it('should redact top-level token values', () => {
201
+ const config = { token: 'secret123', owner: 'myorg' };
202
+ const result = (0, secrets_1.redactConfig)(config);
203
+ expect(result.token).toBe('********');
204
+ expect(result.owner).toBe('myorg');
205
+ });
206
+ it('should redact nested sensitive values', () => {
207
+ const config = {
208
+ github: {
209
+ token: 'ghp_secret',
210
+ owner: 'myorg',
211
+ },
212
+ };
213
+ const result = (0, secrets_1.redactConfig)(config);
214
+ expect(result.github.token).toBe('********');
215
+ expect(result.github.owner).toBe('myorg');
216
+ });
217
+ it('should redact deeply nested values', () => {
218
+ const config = {
219
+ level1: {
220
+ level2: {
221
+ level3: {
222
+ api_key: 'secret',
223
+ },
224
+ },
225
+ },
226
+ };
227
+ const result = (0, secrets_1.redactConfig)(config);
228
+ expect(result.level1.level2.level3.api_key).toBe('********');
229
+ });
230
+ it('should preserve environment variable references', () => {
231
+ const config = { token: '${GITHUB_TOKEN}', secret: '${MY_SECRET}' };
232
+ const result = (0, secrets_1.redactConfig)(config);
233
+ expect(result.token).toBe('${GITHUB_TOKEN}');
234
+ expect(result.secret).toBe('${MY_SECRET}');
235
+ });
236
+ it('should not mutate original config', () => {
237
+ const original = { token: 'secret123' };
238
+ const originalToken = original.token;
239
+ (0, secrets_1.redactConfig)(original);
240
+ expect(original.token).toBe(originalToken);
241
+ });
242
+ it('should handle null and undefined', () => {
243
+ expect((0, secrets_1.redactConfig)(null)).toBe(null);
244
+ expect((0, secrets_1.redactConfig)(undefined)).toBe(undefined);
245
+ });
246
+ it('should handle arrays in config', () => {
247
+ const config = {
248
+ handlers: [{ token: 'secret1' }, { token: 'secret2' }],
249
+ };
250
+ const result = (0, secrets_1.redactConfig)(config);
251
+ expect(result.handlers[0].token).toBe('********');
252
+ expect(result.handlers[1].token).toBe('********');
253
+ });
254
+ it('should handle mixed content', () => {
255
+ const config = {
256
+ work: {
257
+ active_handler: 'github',
258
+ handlers: {
259
+ github: {
260
+ token: 'ghp_secret',
261
+ owner: 'myorg',
262
+ repo: 'myrepo',
263
+ },
264
+ },
265
+ },
266
+ repo: {
267
+ defaults: {
268
+ default_branch: 'main',
269
+ },
270
+ },
271
+ };
272
+ const result = (0, secrets_1.redactConfig)(config);
273
+ expect(result.work.handlers.github.token).toBe('********');
274
+ expect(result.work.handlers.github.owner).toBe('myorg');
275
+ expect(result.work.active_handler).toBe('github');
276
+ expect(result.repo.defaults.default_branch).toBe('main');
277
+ });
278
+ });
279
+ describe('redactValue', () => {
280
+ it('should redact value when key is sensitive', () => {
281
+ expect((0, secrets_1.redactValue)('secret123', 'token')).toBe('********');
282
+ expect((0, secrets_1.redactValue)('secret123', 'password')).toBe('********');
283
+ expect((0, secrets_1.redactValue)('secret123', 'api_key')).toBe('********');
284
+ });
285
+ it('should preserve env var references even with sensitive key', () => {
286
+ expect((0, secrets_1.redactValue)('${GITHUB_TOKEN}', 'token')).toBe('${GITHUB_TOKEN}');
287
+ expect((0, secrets_1.redactValue)('${DB_PASSWORD}', 'password')).toBe('${DB_PASSWORD}');
288
+ });
289
+ it('should redact GitHub tokens regardless of key', () => {
290
+ expect((0, secrets_1.redactValue)('ghp_1234567890abcdefghijklmnopqrstuvwxyz12')).toBe('[REDACTED_GITHUB_TOKEN]');
291
+ });
292
+ it('should redact GitLab tokens regardless of key', () => {
293
+ expect((0, secrets_1.redactValue)('glpat-xxxxxxxxxxxxxxxxxxxx')).toBe('[REDACTED_GITLAB_TOKEN]');
294
+ });
295
+ it('should return original value for non-sensitive content', () => {
296
+ expect((0, secrets_1.redactValue)('myorg', 'owner')).toBe('myorg');
297
+ expect((0, secrets_1.redactValue)('main', 'branch')).toBe('main');
298
+ });
299
+ });
300
+ describe('performance', () => {
301
+ it('should handle large strings efficiently', () => {
302
+ const largeString = 'x'.repeat(100000);
303
+ const start = Date.now();
304
+ (0, secrets_1.sanitizeSecrets)(largeString);
305
+ const elapsed = Date.now() - start;
306
+ // Should complete in under 100ms
307
+ expect(elapsed).toBeLessThan(100);
308
+ });
309
+ it('should handle many secrets efficiently', () => {
310
+ const manySecrets = Array(100)
311
+ .fill('token: ghp_1234567890abcdefghijklmnopqrstuvwxyz12')
312
+ .join('\n');
313
+ const start = Date.now();
314
+ const result = (0, secrets_1.sanitizeSecrets)(manySecrets);
315
+ const elapsed = Date.now() - start;
316
+ expect(elapsed).toBeLessThan(100);
317
+ expect(result).not.toContain('ghp_');
318
+ });
319
+ });
320
+ //# sourceMappingURL=secrets.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.test.js","sourceRoot":"","sources":["../../../src/common/__tests__/secrets.test.ts"],"names":[],"mappings":"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"}
@@ -3,10 +3,8 @@
3
3
  *
4
4
  * Utilities for finding project roots and loading configuration.
5
5
  */
6
- /**
7
- * Find the project root directory by looking for common markers
8
- */
9
- export declare function findProjectRoot(startDir?: string): string;
6
+ import { findProjectRoot as yamlFindProjectRoot } from './yaml-config';
7
+ export { yamlFindProjectRoot as findProjectRoot };
10
8
  /**
11
9
  * Check if a directory is a git repository
12
10
  */
@@ -19,6 +17,10 @@ export declare function getFractaryDir(projectRoot?: string): string;
19
17
  * Ensure a directory exists
20
18
  */
21
19
  export declare function ensureDir(dirPath: string): void;
20
+ /**
21
+ * Config loaders - extract plugin sections from unified YAML config
22
+ * Uses .fractary/core/config.yaml as the single source of truth
23
+ */
22
24
  /**
23
25
  * Load work plugin configuration from unified YAML
24
26
  */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/common/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CA2BxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAGpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI/C;AASD;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/common/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,eAAe,IAAI,mBAAmB,EAAkB,MAAM,eAAe,CAAC;AAIvF,OAAO,EAAE,mBAAmB,IAAI,eAAe,EAAE,CAAC;AAElD;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAGpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI/C;AAED;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAG/D"}
@@ -38,7 +38,7 @@ var __importStar = (this && this.__importStar) || (function () {
38
38
  };
39
39
  })();
40
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
- exports.findProjectRoot = findProjectRoot;
41
+ exports.findProjectRoot = void 0;
42
42
  exports.isGitRepository = isGitRepository;
43
43
  exports.getFractaryDir = getFractaryDir;
44
44
  exports.ensureDir = ensureDir;
@@ -50,33 +50,8 @@ exports.loadFileConfig = loadFileConfig;
50
50
  exports.loadDocsConfig = loadDocsConfig;
51
51
  const fs = __importStar(require("fs"));
52
52
  const path = __importStar(require("path"));
53
- /**
54
- * Find the project root directory by looking for common markers
55
- */
56
- function findProjectRoot(startDir = process.cwd()) {
57
- let currentDir = startDir;
58
- // Common project root markers
59
- const markers = [
60
- 'package.json',
61
- '.git',
62
- 'tsconfig.json',
63
- 'pyproject.toml',
64
- 'setup.py',
65
- ];
66
- while (currentDir !== path.parse(currentDir).root) {
67
- // Check if any marker exists in current directory
68
- for (const marker of markers) {
69
- const markerPath = path.join(currentDir, marker);
70
- if (fs.existsSync(markerPath)) {
71
- return currentDir;
72
- }
73
- }
74
- // Move up one directory
75
- currentDir = path.dirname(currentDir);
76
- }
77
- // If no marker found, return the starting directory
78
- return startDir;
79
- }
53
+ const yaml_config_1 = require("./yaml-config");
54
+ Object.defineProperty(exports, "findProjectRoot", { enumerable: true, get: function () { return yaml_config_1.findProjectRoot; } });
80
55
  /**
81
56
  * Check if a directory is a git repository
82
57
  */
@@ -88,7 +63,7 @@ function isGitRepository(dir = process.cwd()) {
88
63
  * Get the .fractary directory path
89
64
  */
90
65
  function getFractaryDir(projectRoot) {
91
- const root = projectRoot || findProjectRoot();
66
+ const root = projectRoot || (0, yaml_config_1.findProjectRoot)();
92
67
  return path.join(root, '.fractary');
93
68
  }
94
69
  /**
@@ -103,7 +78,6 @@ function ensureDir(dirPath) {
103
78
  * Config loaders - extract plugin sections from unified YAML config
104
79
  * Uses .fractary/core/config.yaml as the single source of truth
105
80
  */
106
- const yaml_config_1 = require("./yaml-config");
107
81
  /**
108
82
  * Load work plugin configuration from unified YAML
109
83
  */
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/common/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/common/config.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaH,0CAGC;AAKD,wCAGC;AAKD,8BAIC;AAUD,wCAGC;AAKD,wCAGC;AAKD,wCAGC;AAKD,sCAGC;AAKD,wCAGC;AAKD,wCAGC;AApFD,uCAAyB;AACzB,2CAA6B;AAC7B,+CAAuF;AAIvD,gGAJJ,6BAAmB,OAIA;AAE/C;;GAEG;AACH,SAAgB,eAAe,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAoB;IACjD,MAAM,IAAI,GAAG,WAAW,IAAI,IAAA,6BAAmB,GAAE,CAAC;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS,CAAC,OAAe;IACvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED;;;GAGG;AAEH;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAoB;IACjD,MAAM,MAAM,GAAG,IAAA,4BAAc,EAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/C,OAAO,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAoB;IACjD,MAAM,MAAM,GAAG,IAAA,4BAAc,EAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/C,OAAO,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAoB;IACjD,MAAM,MAAM,GAAG,IAAA,4BAAc,EAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/C,OAAO,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,WAAoB;IAChD,MAAM,MAAM,GAAG,IAAA,4BAAc,EAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/C,OAAO,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAoB;IACjD,MAAM,MAAM,GAAG,IAAA,4BAAc,EAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/C,OAAO,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAoB;IACjD,MAAM,MAAM,GAAG,IAAA,4BAAc,EAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAC/C,OAAO,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC;AAC9B,CAAC"}
@@ -6,4 +6,5 @@
6
6
  export * from './types';
7
7
  export * from './errors';
8
8
  export * from './config';
9
+ export * from './secrets';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC"}
@@ -22,4 +22,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
22
  __exportStar(require("./types"), exports);
23
23
  __exportStar(require("./errors"), exports);
24
24
  __exportStar(require("./config"), exports);
25
+ __exportStar(require("./secrets"), exports);
25
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;AAEH,0CAAwB;AACxB,2CAAyB;AACzB,2CAAyB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;AAEH,0CAAwB;AACxB,2CAAyB;AACzB,2CAAyB;AACzB,4CAA0B"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @fractary/core - Secrets Sanitization Utilities
3
+ *
4
+ * Unified utilities for redacting sensitive values from strings and objects.
5
+ * Used by CLI, MCP server, and other components to prevent token/secret exposure.
6
+ */
7
+ /**
8
+ * Sanitize token/secret values from error messages and logs.
9
+ * Replaces common secret patterns with [REDACTED].
10
+ *
11
+ * @param message - Error message or log string
12
+ * @returns Sanitized message with secrets redacted
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const safe = sanitizeSecrets('Failed with token ghp_abc123...');
17
+ * // Returns: 'Failed with token [REDACTED_GITHUB_TOKEN]'
18
+ * ```
19
+ */
20
+ export declare function sanitizeSecrets(message: string): string;
21
+ /**
22
+ * Check if a string contains potential security-sensitive information.
23
+ *
24
+ * @param value - String to check
25
+ * @returns True if string might contain secrets
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * containsSecrets('my api_key is xyz'); // true
30
+ * containsSecrets('hello world'); // false
31
+ * ```
32
+ */
33
+ export declare function containsSecrets(value: string): boolean;
34
+ /**
35
+ * Check if a key name indicates it holds a sensitive value.
36
+ *
37
+ * @param key - Key name to check
38
+ * @returns True if the key likely holds a secret
39
+ */
40
+ export declare function isSensitiveKey(key: string): boolean;
41
+ /**
42
+ * Redact sensitive values from a configuration object for display.
43
+ * Preserves environment variable references like `${GITHUB_TOKEN}`.
44
+ *
45
+ * @param config - Configuration object to redact
46
+ * @returns Deep copy with sensitive values redacted
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const config = {
51
+ * token: 'ghp_secret123',
52
+ * owner: 'myorg',
53
+ * nested: { api_key: 'abc123' }
54
+ * };
55
+ * const safe = redactConfig(config);
56
+ * // Returns: { token: '********', owner: 'myorg', nested: { api_key: '********' } }
57
+ * ```
58
+ */
59
+ export declare function redactConfig(config: unknown): unknown;
60
+ /**
61
+ * Redact a single value if it appears to be a secret.
62
+ *
63
+ * @param value - Value to potentially redact
64
+ * @param key - Optional key name for context-aware redaction
65
+ * @returns Redacted value or original value if not sensitive
66
+ */
67
+ export declare function redactValue(value: string, key?: string): string;
68
+ //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/common/secrets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqCH;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBvD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAatD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAgCrD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAmB/D"}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ /**
3
+ * @fractary/core - Secrets Sanitization Utilities
4
+ *
5
+ * Unified utilities for redacting sensitive values from strings and objects.
6
+ * Used by CLI, MCP server, and other components to prevent token/secret exposure.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.sanitizeSecrets = sanitizeSecrets;
10
+ exports.containsSecrets = containsSecrets;
11
+ exports.isSensitiveKey = isSensitiveKey;
12
+ exports.redactConfig = redactConfig;
13
+ exports.redactValue = redactValue;
14
+ /**
15
+ * Sensitive key names that should be redacted
16
+ */
17
+ const SENSITIVE_KEYS = ['token', 'key', 'secret', 'password', 'api_key', 'apikey', 'auth'];
18
+ /**
19
+ * Token patterns for detection and redaction
20
+ */
21
+ const TOKEN_PATTERNS = {
22
+ // GitHub tokens (ghp_, gho_, ghs_, ghu_, ghr_)
23
+ github: /gh[posuhr]_[A-Za-z0-9]{36,}/gi,
24
+ // GitLab tokens
25
+ gitlab: /glpat-[A-Za-z0-9_\-]{20,}/gi,
26
+ // Bearer tokens
27
+ bearer: /Bearer\s+[A-Za-z0-9\-._~+/]+=*/gi,
28
+ // Basic auth
29
+ basic: /Basic\s+[A-Za-z0-9+/=]+/gi,
30
+ // Generic key-value patterns (JSON, env vars, config)
31
+ keyValue: /(token|key|password|secret|api[_-]?key|access[_-]?token|auth[_-]?token|bearer)["']?\s*[=:]\s*["']?[^\s"',}]+/gi,
32
+ // Generic API keys (long alphanumeric strings after common keywords)
33
+ genericKey: /(api[_-]?key|apikey|access[_-]?key)\s*[=:]\s*["']?[A-Za-z0-9\-._~+/]{20,}["']?/gi,
34
+ };
35
+ /**
36
+ * Redaction placeholders
37
+ */
38
+ const REDACTED = {
39
+ default: '[REDACTED]',
40
+ github: '[REDACTED_GITHUB_TOKEN]',
41
+ gitlab: '[REDACTED_GITLAB_TOKEN]',
42
+ value: '********',
43
+ };
44
+ /**
45
+ * Sanitize token/secret values from error messages and logs.
46
+ * Replaces common secret patterns with [REDACTED].
47
+ *
48
+ * @param message - Error message or log string
49
+ * @returns Sanitized message with secrets redacted
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const safe = sanitizeSecrets('Failed with token ghp_abc123...');
54
+ * // Returns: 'Failed with token [REDACTED_GITHUB_TOKEN]'
55
+ * ```
56
+ */
57
+ function sanitizeSecrets(message) {
58
+ return (message
59
+ // Redact tokens in key-value patterns (JSON, env vars, config)
60
+ .replace(TOKEN_PATTERNS.keyValue, '$1: [REDACTED]')
61
+ // Redact bearer tokens
62
+ .replace(TOKEN_PATTERNS.bearer, 'Bearer [REDACTED]')
63
+ // Redact Basic auth
64
+ .replace(TOKEN_PATTERNS.basic, 'Basic [REDACTED]')
65
+ // Redact GitHub tokens (ghp_, gho_, ghs_, ghu_, ghr_)
66
+ .replace(TOKEN_PATTERNS.github, REDACTED.github)
67
+ // Redact GitLab tokens
68
+ .replace(TOKEN_PATTERNS.gitlab, REDACTED.gitlab)
69
+ // Redact generic API keys (long alphanumeric strings after common keywords)
70
+ .replace(TOKEN_PATTERNS.genericKey, '$1: [REDACTED]'));
71
+ }
72
+ /**
73
+ * Check if a string contains potential security-sensitive information.
74
+ *
75
+ * @param value - String to check
76
+ * @returns True if string might contain secrets
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * containsSecrets('my api_key is xyz'); // true
81
+ * containsSecrets('hello world'); // false
82
+ * ```
83
+ */
84
+ function containsSecrets(value) {
85
+ const secretPatterns = [
86
+ /token/i,
87
+ /password/i,
88
+ /secret/i,
89
+ /api[_-]?key/i,
90
+ /bearer/i,
91
+ /authorization/i,
92
+ /gh[posuhr]_/,
93
+ /glpat-/,
94
+ ];
95
+ return secretPatterns.some((pattern) => pattern.test(value));
96
+ }
97
+ /**
98
+ * Check if a key name indicates it holds a sensitive value.
99
+ *
100
+ * @param key - Key name to check
101
+ * @returns True if the key likely holds a secret
102
+ */
103
+ function isSensitiveKey(key) {
104
+ const lowerKey = key.toLowerCase();
105
+ return SENSITIVE_KEYS.some((sensitiveKey) => lowerKey.includes(sensitiveKey));
106
+ }
107
+ /**
108
+ * Redact sensitive values from a configuration object for display.
109
+ * Preserves environment variable references like `${GITHUB_TOKEN}`.
110
+ *
111
+ * @param config - Configuration object to redact
112
+ * @returns Deep copy with sensitive values redacted
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * const config = {
117
+ * token: 'ghp_secret123',
118
+ * owner: 'myorg',
119
+ * nested: { api_key: 'abc123' }
120
+ * };
121
+ * const safe = redactConfig(config);
122
+ * // Returns: { token: '********', owner: 'myorg', nested: { api_key: '********' } }
123
+ * ```
124
+ */
125
+ function redactConfig(config) {
126
+ if (!config)
127
+ return config;
128
+ // Deep clone to avoid mutating original
129
+ const redacted = JSON.parse(JSON.stringify(config));
130
+ function redactObject(obj) {
131
+ for (const key in obj) {
132
+ const value = obj[key];
133
+ if (typeof value === 'string') {
134
+ // Check if key indicates sensitive data
135
+ if (isSensitiveKey(key)) {
136
+ // Preserve environment variable references
137
+ if (value.includes('${')) {
138
+ // Keep env var reference as-is
139
+ continue;
140
+ }
141
+ // Redact actual values
142
+ obj[key] = REDACTED.value;
143
+ }
144
+ }
145
+ else if (typeof value === 'object' && value !== null) {
146
+ redactObject(value);
147
+ }
148
+ }
149
+ }
150
+ if (typeof redacted === 'object' && redacted !== null) {
151
+ redactObject(redacted);
152
+ }
153
+ return redacted;
154
+ }
155
+ /**
156
+ * Redact a single value if it appears to be a secret.
157
+ *
158
+ * @param value - Value to potentially redact
159
+ * @param key - Optional key name for context-aware redaction
160
+ * @returns Redacted value or original value if not sensitive
161
+ */
162
+ function redactValue(value, key) {
163
+ // If key suggests it's sensitive, redact
164
+ if (key && isSensitiveKey(key)) {
165
+ // Preserve env var references
166
+ if (value.includes('${')) {
167
+ return value;
168
+ }
169
+ return REDACTED.value;
170
+ }
171
+ // Check for known token patterns
172
+ if (TOKEN_PATTERNS.github.test(value)) {
173
+ return REDACTED.github;
174
+ }
175
+ if (TOKEN_PATTERNS.gitlab.test(value)) {
176
+ return REDACTED.gitlab;
177
+ }
178
+ return value;
179
+ }
180
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/common/secrets.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,17 +1,23 @@
1
1
  {
2
2
  "name": "@fractary/core",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Fractary Core SDK - Primitive operations for work tracking, repository management, specifications, logging, file storage, and documentation",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "typesVersions": {
8
8
  "*": {
9
+ "config": [
10
+ "dist/config/index.d.ts"
11
+ ],
9
12
  "common/config": [
10
13
  "dist/common/config.d.ts"
11
14
  ],
12
15
  "common/yaml-config": [
13
16
  "dist/common/yaml-config.d.ts"
14
17
  ],
18
+ "common/secrets": [
19
+ "dist/common/secrets.d.ts"
20
+ ],
15
21
  "work": [
16
22
  "dist/work/index.d.ts"
17
23
  ],
@@ -37,6 +43,10 @@
37
43
  "types": "./dist/index.d.ts",
38
44
  "default": "./dist/index.js"
39
45
  },
46
+ "./config": {
47
+ "types": "./dist/config/index.d.ts",
48
+ "default": "./dist/config/index.js"
49
+ },
40
50
  "./work": {
41
51
  "types": "./dist/work/index.d.ts",
42
52
  "default": "./dist/work/index.js"
@@ -68,6 +78,10 @@
68
78
  "./common/config": {
69
79
  "types": "./dist/common/config.d.ts",
70
80
  "default": "./dist/common/config.js"
81
+ },
82
+ "./common/secrets": {
83
+ "types": "./dist/common/secrets.d.ts",
84
+ "default": "./dist/common/secrets.js"
71
85
  }
72
86
  },
73
87
  "files": [