mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-20 05:11:48 +00:00
feat(config): add unified YAML config with migration support
Implements unified config.yaml format consolidating: - config.json (API profiles) - profiles.json (account metadata) - *.settings.json (env vars) Features: - Auto-migration from v1 JSON to v2 YAML with backup - Secrets separation into secrets.yaml (chmod 600) - Enhanced YAML output with section comments - CLIProxy OAuth settings migration with env var support - Feature flag for gradual rollout (CCS_UNIFIED_CONFIG=1) - Rollback support via ccs migrate --rollback New commands: - ccs migrate - Run migration - ccs migrate --dry-run - Preview changes - ccs migrate --rollback <path> - Restore from backup - ccs migrate --list-backups - List available backups Closes #75
This commit is contained in:
1 parent
0e46b6ba10
commit
b621b8e47b
21 files changed
+2575
-141
No files matched your search
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Sensitive Key Detection Utilities
|
||||
*
|
||||
* Shared patterns for detecting secret/sensitive environment variable keys.
|
||||
* Used by migration (secrets separation) and UI (masking).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Patterns that match sensitive keys (API keys, tokens, passwords).
|
||||
* More specific than substring matching to avoid false positives.
|
||||
*/
|
||||
export const SENSITIVE_KEY_PATTERNS = [
|
||||
/^ANTHROPIC_AUTH_TOKEN$/, // Exact match for Anthropic auth token
|
||||
/_API_KEY$/, // Keys ending with _API_KEY
|
||||
/_AUTH_TOKEN$/, // Keys ending with _AUTH_TOKEN
|
||||
/_SECRET$/, // Keys ending with _SECRET
|
||||
/_SECRET_KEY$/, // Keys ending with _SECRET_KEY
|
||||
/^API_KEY$/, // Exact match for API_KEY
|
||||
/^AUTH_TOKEN$/, // Exact match for AUTH_TOKEN
|
||||
/^SECRET$/, // Exact match for SECRET
|
||||
/_PASSWORD$/, // Keys ending with _PASSWORD
|
||||
/^PASSWORD$/, // Exact match for PASSWORD
|
||||
/_CREDENTIAL$/, // Keys ending with _CREDENTIAL
|
||||
/_PRIVATE_KEY$/, // Keys ending with _PRIVATE_KEY
|
||||
];
|
||||
|
||||
/**
|
||||
* Check if a key name contains a secret/sensitive value.
|
||||
* Used during migration to separate secrets from config.
|
||||
*
|
||||
* @param key - Environment variable key name
|
||||
* @returns true if the key likely contains sensitive data
|
||||
*/
|
||||
export function isSensitiveKey(key: string): boolean {
|
||||
return SENSITIVE_KEY_PATTERNS.some((pattern) => pattern.test(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mask a sensitive value for display.
|
||||
* Shows first 4 and last 4 characters, replaces middle with asterisks.
|
||||
*
|
||||
* @param value - The sensitive value to mask
|
||||
* @returns Masked value like "sk-a****xyz1"
|
||||
*/
|
||||
export function maskSensitiveValue(value: string): string {
|
||||
if (!value || value.length <= 8) {
|
||||
return '*'.repeat(value?.length || 0);
|
||||
}
|
||||
return value.slice(0, 4) + '*'.repeat(Math.max(0, value.length - 8)) + value.slice(-4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mask all sensitive keys in an env object.
|
||||
*
|
||||
* @param env - Environment variables object
|
||||
* @returns New object with sensitive values masked
|
||||
*/
|
||||
export function maskSensitiveEnv(env: Record<string, string>): Record<string, string> {
|
||||
const masked: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(env)) {
|
||||
masked[key] = isSensitiveKey(key) ? maskSensitiveValue(value) : value;
|
||||
}
|
||||
return masked;
|
||||
}
|
||||
Reference in new issue
Block a user