#!/usr/bin/env node import { randomBytes } from 'crypto'; import { readFileSync, writeFileSync, existsSync } from 'fs'; function get_arg(argv, flag) { const i = argv.indexOf(flag); return i !== -1 ? argv[i + 1] : null; } function has_flag(argv, flag) { return argv.includes(flag); } function parse_names(value, flag) { if (!value) { console.error(`${flag} requires a comma-separated list of usernames`); process.exit(1); } return value.split(',').map(s => s.trim()).filter(Boolean); } function generate_secret() { return randomBytes(32).toString('hex'); } function read_secrets_file(input_path) { if (!existsSync(input_path)) { console.error(`Secrets file not found: ${input_path}`); process.exit(1); } try { return JSON.parse(readFileSync(input_path, 'utf8')); } catch (err) { console.error(`Cannot read secrets file: ${err.message}`); process.exit(1); } } function write_secrets_file(output_path, data) { writeFileSync(output_path, JSON.stringify(data, null, '\t') + '\n', 'utf8'); console.log(`Written: ${output_path}`); } const argv = process.argv; const create_arg = get_arg(argv, '--create'); const filter_arg = get_arg(argv, '--filter'); const input_arg = get_arg(argv, '--input') || 'secrets.json'; const output_arg = get_arg(argv, '--output'); if (!create_arg && !filter_arg) { console.error( 'Usage:\n' + ' ccc-keygen --create [--output secrets.json]\n' + ' ccc-keygen --filter [--input secrets.json] [--output filtered-secrets.json]' ); process.exit(1); } if (create_arg) { const names = parse_names(create_arg, '--create'); const output_path = output_arg || 'secrets.json'; const users = {}; for (const name of names) { users[name] = { secret: generate_secret(), canApprove: [] }; } write_secrets_file(output_path, { users }); console.log(`Created users: ${names.join(', ')}`); console.log('Edit canApprove lists to configure approval permissions.'); } if (filter_arg) { const names = parse_names(filter_arg, '--filter'); const output_path = output_arg || 'filtered-secrets.json'; const source = read_secrets_file(input_arg); const users = {}; for (const name of names) { if (!source.users?.[name]) { console.error(`User '${name}' not found in ${input_arg}`); process.exit(1); } users[name] = source.users[name]; } write_secrets_file(output_path, { users }); console.log(`Filtered users: ${names.join(', ')}`); }