From 0a510b7f9a0c9187e692f9acf487360b5ea490b3 Mon Sep 17 00:00:00 2001 From: Padreug Date: Wed, 27 May 2026 17:04:31 +0200 Subject: [PATCH] fix(#7): route error responses to the request's kind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The catch block in handleRequest and both response paths in create_account pass `NDKKind.NostrConnectAdmin` as the response kind. That constant does NOT exist in NDK 2.8.1 — only `NostrConnect = 24133` is exported — so it resolves to `undefined` and NDKNostrRpc.sendResponse falls through to its own default of `NDKKind.NostrConnect = 24133`. Net effect: any error response to an admin-channel (kind 24134) request is published on the NIP-46 signing channel (24133) instead, which clients subscribed for 24134 never see. Looks like a transport-layer NDK-echo / silent-drop issue from the client's perspective, but the bunker IS publishing reliably — just on the wrong kind. Mirror `req.event.kind` so the error response goes back on the same channel the request came in on. Same pattern the unknown-method path and create_account's validation-error path already used; just propagate it to the remaining sites. Drops the now-unused NDKKind import from create_account.ts. Validated end-to-end against the local bunker via the lnbits-side admin spike harness — after this fix + the migration entrypoint fix + the policyId type fix, all 9 spike steps including NIP-46 sign_event pass with Schnorr-valid signatures. See coordination log entry 2026-05-27T14:30Z. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/daemon/admin/commands/create_account.ts | 17 ++++++++++++----- src/daemon/admin/index.ts | 10 +++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/daemon/admin/commands/create_account.ts b/src/daemon/admin/commands/create_account.ts index e4632d6..f3c026a 100644 --- a/src/daemon/admin/commands/create_account.ts +++ b/src/daemon/admin/commands/create_account.ts @@ -1,4 +1,4 @@ -import { Hexpubkey, NDKKind, NDKPrivateKeySigner, NDKRpcRequest, NDKUserProfile } from "@nostr-dev-kit/ndk"; +import { Hexpubkey, NDKPrivateKeySigner, NDKRpcRequest, NDKUserProfile } from "@nostr-dev-kit/ndk"; import AdminInterface from ".."; import { nip19 } from 'nostr-tools'; import { setupSkeletonProfile } from "../../lib/profile"; @@ -136,7 +136,7 @@ export default async function createAccount(admin: AdminInterface, req: NDKRpcRe } /** - * This is where the real work of creating the private key, wallet, nip-05, granting access, etc happen + * This is where the real work of creating the private key, wallet, nip-05, granting access, etc happen — pragma: allowlist secret */ export async function createAccountReal( admin: AdminInterface, @@ -209,11 +209,18 @@ export async function createAccountReal( // access it without having to go through an approval flow await grantPermissions(req, keyName); - return admin.rpc.sendResponse(req.id, req.pubkey, generatedUser.pubkey, NDKKind.NostrConnectAdmin); + // NDKKind.NostrConnectAdmin doesn't exist in NDK 2.8.1 — it resolves + // to `undefined` and sendResponse defaults to NDKKind.NostrConnect + // (24133), sending the response on the wrong channel. Mirror the + // request's kind so the response goes back on the same channel the + // client subscribed for. Filed as part of aiolabs/nsecbunkerd#7 + // diagnosis 2026-05-27. + const originalKind = req.event.kind!; + return admin.rpc.sendResponse(req.id, req.pubkey, generatedUser.pubkey, originalKind); } catch (e: any) { console.trace('error', e); - return admin.rpc.sendResponse(req.id, req.pubkey, "error", NDKKind.NostrConnectAdmin, - e.message); + const originalKind = req.event.kind!; + return admin.rpc.sendResponse(req.id, req.pubkey, "error", originalKind, e.message); } } diff --git a/src/daemon/admin/index.ts b/src/daemon/admin/index.ts index 4684fcb..5adafe8 100644 --- a/src/daemon/admin/index.ts +++ b/src/daemon/admin/index.ts @@ -209,7 +209,15 @@ class AdminInterface { } } catch (err: any) { debug(`Error handling request ${req.method}: ${err?.message??err}`, req.params); - return this.rpc.sendResponse(req.id, req.pubkey, "error", NDKKind.NostrConnectAdmin, err?.message); + // NDKKind.NostrConnectAdmin doesn't exist in NDK 2.8.1 — using it + // makes sendResponse fall through to its default of 24133, which + // sends the error on a different channel than the request came in + // on. Mirror req.event.kind so the response goes back where the + // client is listening. Filed as part of aiolabs/nsecbunkerd#7 + // diagnosis 2026-05-27. + const originalKind = req.event.kind!; + console.log(`⚠️ HANDLE_REQUEST_ERROR method=${req.method} id=${req.id} kind=${originalKind} err=${err?.message ?? err}`); + return this.rpc.sendResponse(req.id, req.pubkey, "error", originalKind, err?.message); } }