@kya-os/cli
Version:
CLI for KYA-OS MCP-I setup and management
127 lines ⢠6 kB
JavaScript
import chalk from "chalk";
import ora from "ora";
import { MCPIdentity } from "@kya-os/mcp-i";
import { EnvManager } from "../utils/env-manager.js";
import { confirmRotation, showSuccess, showError, showWarning, } from "../utils/prompts.js";
import { cliEffects, EffectTrigger } from "../effects/cli-integration.js";
export async function rotate(options) {
console.log(chalk.cyan("\nš Key Rotation\n"));
// Check for existing identity
const envManager = new EnvManager();
const processVars = envManager.getFromProcess();
if (!processVars.MCP_IDENTITY_AGENT_DID) {
showError('No MCP-I identity found. Run "npx kya-os init" first.');
return;
}
// Confirm rotation
if (!options.force) {
const { confirm, reason } = await confirmRotation();
if (!confirm) {
console.log(chalk.gray("\nRotation cancelled."));
return;
}
options.reason = reason;
}
showWarning("Key rotation will generate new cryptographic keys.");
console.log("The old keys will remain valid during a 7-day grace period.\n");
const spinner = ora("Rotating keys...").start();
try {
// Initialize identity from existing configuration
const identity = await MCPIdentity.init();
// Check if rotation is available
const keyHealth = identity.checkKeyHealth();
if (!keyHealth) {
spinner.fail("Key rotation not available (using memory storage)");
console.log(chalk.blue("ā¹ļø Key rotation requires file storage. Serverless environments cannot rotate keys."));
return;
}
// Show current key health
spinner.info("Current key status:");
console.log(` Age: ${Math.floor(keyHealth.age / (24 * 60 * 60 * 1000))} days`);
console.log(` Signatures: ${keyHealth.signatureCount.toLocaleString()}`);
console.log(` Should rotate: ${keyHealth.shouldRotate ? chalk.yellow("Yes") : chalk.green("No")}`);
// Show burn effect for old keys
spinner.stop();
await cliEffects.showEffect(EffectTrigger.KEY_ROTATION, `š„ Rotating cryptographic keys...\n\n` +
`Old Key: ${processVars.MCP_IDENTITY_AGENT_PUBLIC_KEY?.substring(0, 16)}...\n` +
`Status: BURNING`);
// Perform rotation
spinner.start("Contacting registry...");
const result = await identity.rotateKeys(options.reason);
if (result.success) {
spinner.succeed("Keys rotated successfully!");
// Show beams effect for new keys
const newKeysText = `š ${chalk.bold("New Keys Generated:")}\n` +
` Public Key: ${identity.publicKey.substring(0, 32)}...\n` +
` Grace period ends: ${new Date(result.gracePeriodEnd).toLocaleDateString()}\n` +
` Old keys remain valid until then`;
await cliEffects.showCustomEffect("beams", newKeysText, {
config: {
duration: 3000,
beamColors: ["00ff00", "00ffff", "ffffff"],
beamCount: 5,
baseColor: "404040",
},
});
// Get new identity info
const newVars = {
MCP_IDENTITY_AGENT_DID: identity.did,
MCP_IDENTITY_AGENT_PUBLIC_KEY: identity.publicKey,
MCP_IDENTITY_AGENT_PRIVATE_KEY: identity.privateKey || "",
MCP_IDENTITY_AGENT_ID: identity.agentId || "",
MCP_IDENTITY_AGENT_SLUG: identity.agentSlug || "",
};
// Update environment files
console.log(`\n${chalk.bold("š Updating Environment Files:")}`);
try {
const result = await envManager.smartInsertMcpVariables(newVars, {
force: true,
});
if (result.success) {
const operation = result.operation === "created"
? "Created"
: result.operation === "updated"
? "Updated"
: "Replaced variables in";
console.log(` ā ${operation} ${chalk.green(result.targetFile)}`);
// Show warnings if any
if (result.warnings.length > 0) {
result.warnings.forEach((warning) => {
console.log(` ${chalk.yellow("ā ")} ${warning}`);
});
}
}
else {
console.log(` ā Failed to update environment files: ${result.warnings.join(", ")}`);
}
}
catch (error) {
console.log(` ā Failed to update environment files: ${error.message}`);
}
showSuccess("Key rotation complete!");
console.log(`\n${chalk.bold("ā ļø Important Next Steps:")}`);
console.log("\n1. Update production environment variables:");
console.log(` ${chalk.cyan("npx kya-os env copy")}`);
console.log("\n2. Deploy your application with new keys");
console.log("\n3. Monitor for any authentication issues");
console.log(`\n${chalk.yellow("Note:")} Both old and new keys will work for 7 days.`);
}
else {
spinner.fail("Key rotation failed");
showError(result.error || "Unknown error during rotation");
}
}
catch (error) {
spinner.fail("Key rotation failed");
if (error.message?.includes("429")) {
showError("Rate limit exceeded. Please try again later.");
}
else if (error.message?.includes("Network")) {
showError("Network error. Check your internet connection.");
}
else {
showError(error.message || "Failed to rotate keys");
}
}
}
//# sourceMappingURL=rotate.js.map