mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-11 03:13:12 +00:00
Epic P5. Splits 4 test-backed god-files into focused submodules using the Monster File Splitting methodology; each original file is now a thin barrel re-exporting the full public surface, so consumers are unchanged. - src/management/shared-manager.ts (1631 -> barrel 21 + 10 submodules, max 337 LOC): fs-helpers, symlink-helpers, plugin-metadata-normalizer, plugin-layout-internals, shared-dir-linker, project-context-sync, project-memory-sync, migrations, orchestrator, types. - src/web-server/routes/cliproxy-stats-routes.ts (1216 -> barrel 23 + 8 submodules, max 290 LOC): shared, quota-helpers, version-helpers, restart-route, quota-routes, error-log-routes, config-routes, router. - src/commands/persist-command.ts (1071 -> barrel + 8 submodules, max 258): types, arg-parsing, secure-file, backup-rotation, secret-detection, receipt, help, handler. - src/commands/cliproxy/quota-subcommand.ts (1130 -> barrel + 14 submodules, max 303): types, format-helpers, codex/claude-window-helpers, provider-runtime, handlers, per-provider sections. Public API preserved verbatim (default + named exports). All P3 structured logging and P4 typed errors preserved through the splits. Each resulting file < 400 LOC. Existing tests (shared-manager x4, cliproxy-stats x4, persist x2, quota-subcommand x1) green, unchanged. Metric: files > 400 LOC 95 -> 91. validate + validate:ci-parity green.
55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
/**
|
|
* Persist Command - Secret Detection & Masking
|
|
*
|
|
* Identifies sensitive env var names (TOKEN/KEY/SECRET/etc.) so the persist
|
|
* preview can mask their values before printing to the terminal.
|
|
*/
|
|
|
|
/** Mask API key for display (show first 4 and last 4 chars) */
|
|
export function maskApiKey(key: string): string {
|
|
if (key.length <= 12) {
|
|
return '****';
|
|
}
|
|
return `${key.slice(0, 4)}...${key.slice(-4)}`;
|
|
}
|
|
|
|
const SENSITIVE_ENV_PARTS = new Set([
|
|
'TOKEN',
|
|
'KEY',
|
|
'SECRET',
|
|
'PASSWORD',
|
|
'PASS',
|
|
'AUTH',
|
|
'CREDENTIAL',
|
|
'PRIVATE',
|
|
'ACCESS',
|
|
'REFRESH',
|
|
'APIKEY',
|
|
]);
|
|
|
|
export function splitSensitiveKeyParts(key: string): string[] {
|
|
const withCamelCaseBoundaries = key.replace(/([a-z0-9])([A-Z])/g, '$1_$2');
|
|
return withCamelCaseBoundaries
|
|
.toUpperCase()
|
|
.split(/[^A-Z0-9]+/)
|
|
.filter(Boolean);
|
|
}
|
|
|
|
export function isSensitiveEnvKey(key: string): boolean {
|
|
const parts = splitSensitiveKeyParts(key);
|
|
if (parts.some((part) => SENSITIVE_ENV_PARTS.has(part))) {
|
|
return true;
|
|
}
|
|
|
|
const compact = parts.join('');
|
|
return (
|
|
compact.includes('TOKEN') ||
|
|
compact.includes('APIKEY') ||
|
|
compact.includes('ACCESSKEY') ||
|
|
compact.includes('AUTHKEY') ||
|
|
compact.includes('SECRET') ||
|
|
compact.includes('PASSWORD') ||
|
|
compact.includes('CREDENTIAL')
|
|
);
|
|
}
|