This repository was archived by the owner on Jun 27, 2026. It is now read-only.
fix(mill): use per-node Nostr secret for identity so children get distinct keys (#266)#267
Open
ALLiDoizCode wants to merge 1 commit into
Open
fix(mill): use per-node Nostr secret for identity so children get distinct keys (#266)#267ALLiDoizCode wants to merge 1 commit into
ALLiDoizCode wants to merge 1 commit into
Conversation
…tinct keys (#266) A mill provisioned at a non-zero derivation index (nodes.yaml records mill at index 1) was running with the apex/town key (index 0): its entrypoint deleted the supplied per-node `NODE_NOSTR_SECRET_KEY` whenever `MILL_MNEMONIC` was set ("mnemonic takes priority") and `startMill` always derived identity via `fromMnemonic(mnemonic)` → index 0. Two nodes sharing one Nostr pubkey collide on the replaceable kind:10032 slot, so the mill's announcement overwrote the town's on the relay. The orchestrator already derives and passes each child's distinct key (`buildNodeEnv` → compose `NODE_NOSTR_SECRET_KEY: ${MILL_SECRET_KEY}`, verified: that key derives to nodes.yaml's mill pubkey 632981e0…, ≠ town e93eeac8…). The fix is to USE it: - mill.ts: `validateConfig` now allows BOTH mnemonic + secretKey (mnemonic drives BIP-32 swap-key derivation; secretKey overrides the Nostr identity). `startMill` derives identity from `config.secretKey` when present, else the mnemonic. - entrypoint-mill.ts / cli.ts: keep the per-node secret as an identity override when a mnemonic is also present (instead of deleting it). DVM already uses its pre-derived index-2 `NODE_NOSTR_SECRET_KEY` (no mnemonic), so it is unaffected. Mill unit tests updated (both-supplied is now valid) — 189 pass. Live container re-verification needs the mill image rebuilt (CI; local build OOMs on the mina-zkapp/o1js step). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #266.
Problem
A mill provisioned at a non-zero derivation index ran with the apex/town key (index 0). Two nodes sharing one Nostr pubkey collide on the replaceable
kind:10032slot, so the mill's announcement overwrote the town's on the relay (surfaced during the #264 e2e).Root cause:
entrypoint-mill.tsdeleted the supplied per-nodeNODE_NOSTR_SECRET_KEYwheneverMILL_MNEMONICwas set ("mnemonic takes priority"), andstartMillalways derived identity viafromMnemonic(mnemonic)→ index 0.Key insight
The orchestrator already derives and passes each child's distinct key —
buildNodeEnv→ composeNODE_NOSTR_SECRET_KEY: ${MILL_SECRET_KEY}. Verified on the live apex: that key derives to nodes.yaml's mill pubkey632981e0…(≠ towne93eeac8…). The fix is just to use it.Fix
mill.ts—validateConfignow allows bothmnemonic+secretKey(mnemonic drives BIP-32 swap-key derivation;secretKeyoverrides the Nostr identity).startMillderives identity fromconfig.secretKeywhen present, else the mnemonic.entrypoint-mill.ts/cli.ts— keep the per-node secret as an identity override when a mnemonic is also present (instead of deleting it).DVM already uses its pre-derived index-2
NODE_NOSTR_SECRET_KEY(no mnemonic) → unaffected.Tests / verification
NODE_NOSTR_SECRET_KEYderives to632981e0…(distinct from town, matches nodes.yaml).632981e0) needs the mill image rebuilt — local build OOMs on themina-zkapp/o1js step, so it's deferred to CI.🤖 Generated with Claude Code