ndr: remove privateKey from clawdbot config

ndr manages its own identity in its config.json - no need for
clawdbot to know or store the private key.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Iris Deploy 2026-01-28 08:58:03 +01:00
parent fb2d16218b
commit 01e03d8938
4 changed files with 3 additions and 69 deletions

View File

@ -157,7 +157,6 @@ export const ndrPlugin: ChannelPlugin<ResolvedNdrAccount> = {
}),
buildChannelSummary: ({ snapshot }) => ({
configured: snapshot.configured ?? false,
publicKey: snapshot.publicKey ?? null,
running: snapshot.running ?? false,
lastStartAt: snapshot.lastStartAt ?? null,
lastStopAt: snapshot.lastStopAt ?? null,
@ -168,7 +167,6 @@ export const ndrPlugin: ChannelPlugin<ResolvedNdrAccount> = {
name: account.name,
enabled: account.enabled,
configured: account.configured,
publicKey: account.publicKey,
running: runtime?.running ?? false,
lastStartAt: runtime?.lastStartAt ?? null,
lastStopAt: runtime?.lastStopAt ?? null,
@ -183,17 +181,13 @@ export const ndrPlugin: ChannelPlugin<ResolvedNdrAccount> = {
const account = ctx.account;
ctx.setStatus({
accountId: account.accountId,
publicKey: account.publicKey,
});
ctx.log?.info(`[${account.accountId}] starting NDR provider (pubkey: ${account.publicKey})`);
// Note: account.configured is always true since ndr auto-generates identity
ctx.log?.info(`[${account.accountId}] starting NDR provider`);
const runtime = getNdrRuntime();
const bus = await startNdrBus({
accountId: account.accountId,
privateKey: account.privateKey,
relays: account.relays,
ndrPath: account.ndrPath,
dataDir: account.dataDir,

View File

@ -4,9 +4,6 @@ import { z } from "zod";
* NDR channel configuration schema
*/
export const NdrConfigSchema = z.object({
/** Private key for signing (hex or nsec format). If not provided, ndr auto-generates one. */
privateKey: z.string().optional(),
/** Owner's pubkey (npub or hex). Only messages from this pubkey are handled as commands. */
ownerPubkey: z.string().optional(),

View File

@ -9,7 +9,6 @@ export interface NdrMessageMedia {
export interface NdrBusOptions {
accountId: string;
privateKey: string;
relays: string[];
ndrPath: string;
dataDir: string | null;
@ -38,7 +37,6 @@ export interface NdrBusHandle {
*/
export async function startNdrBus(options: NdrBusOptions): Promise<NdrBusHandle> {
const {
privateKey,
relays,
ndrPath,
dataDir,
@ -58,31 +56,7 @@ export async function startNdrBus(options: NdrBusOptions): Promise<NdrBusHandle>
baseArgs.push("--data-dir", dataDir);
}
// Initialize: login with provided key, or let ndr auto-generate on first use
if (privateKey) {
await runNdrCommand(ndrPath, [...baseArgs, "login", privateKey]);
}
// If no privateKey, ndr will auto-generate identity when needed (invite/listen/send)
// Update relay config if needed (preserve existing config like private_key)
if (dataDir && relays.length > 0) {
const configPath = `${dataDir}/config.json`;
const fs = await import("fs/promises");
try {
let existingConfig: Record<string, unknown> = {};
try {
const content = await fs.readFile(configPath, "utf-8");
existingConfig = JSON.parse(content);
} catch {
// Config doesn't exist yet, start fresh
}
// Merge relays into existing config, preserving other fields like private_key
const mergedConfig = { ...existingConfig, relays };
await fs.writeFile(configPath, JSON.stringify(mergedConfig, null, 2));
} catch {
// Config dir may not exist yet, ndr will create it
}
}
// ndr manages its own identity in its config.json (auto-generates on first use)
// Start listening for messages and invite responses (both handled by `ndr listen`)
const startListening = () => {

View File

@ -1,5 +1,4 @@
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import { getPublicKey } from "nostr-tools";
import { homedir } from "os";
import { join } from "path";
import { DEFAULT_RELAYS, type NdrConfig } from "./config-schema.js";
@ -19,8 +18,6 @@ export interface ResolvedNdrAccount {
name: string;
enabled: boolean;
configured: boolean;
privateKey: string;
publicKey: string | null;
ownerPubkey: string | null;
relays: string[];
ndrPath: string;
@ -60,21 +57,7 @@ export function resolveNdrAccount(opts: {
const channels = (cfg.channels ?? {}) as Record<string, unknown>;
const ndrConfig = (channels.ndr ?? {}) as NdrConfig;
const privateKey = ndrConfig.privateKey ?? "";
let publicKey: string | null = null;
if (privateKey) {
try {
// Handle hex format
const keyBytes = hexToBytes(privateKey);
publicKey = getPublicKey(keyBytes);
} catch {
// Invalid key format
}
}
// ndr auto-generates identity if not provided, so we're always "configured"
// The actual identity will be created/loaded by ndr on first use
// ndr manages its own identity in its config.json (auto-generates on first use)
const configured = true;
const relays = ndrConfig.relays ?? DEFAULT_RELAYS;
@ -89,8 +72,6 @@ export function resolveNdrAccount(opts: {
name: ndrConfig.name ?? "NDR",
enabled: ndrConfig.enabled !== false,
configured,
privateKey,
publicKey,
ownerPubkey,
relays,
ndrPath: ndrConfig.ndrPath ?? "ndr",
@ -100,18 +81,6 @@ export function resolveNdrAccount(opts: {
};
}
/**
* Convert hex string to Uint8Array
*/
function hexToBytes(hex: string): Uint8Array {
const cleaned = hex.replace(/^0x/, "");
const bytes = new Uint8Array(cleaned.length / 2);
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(cleaned.substr(i * 2, 2), 16);
}
return bytes;
}
/**
* Normalize a pubkey to hex format
*/