Files
mantra-kmp/docs
Kgothatso Ngako c49914818a docs: plan nsec sign-in, and the ten call sites that make it small
An nsec is a BIP32 leaf of the seed at m/44'/1237'/0'/0/0, and the
derivation runs one way, so an nsec can never have a wallet behind it. What
makes the feature tractable anyway is that nothing in the app reads the
wallet except the nostr key -- ten sites, all the same expression -- so the
plan puts an Identity in front of the wallet and gives an nsec an identity
with no node behind it.

Eight phases: the identity type; a sibling key file in the library under the
one keystore alias Android will accept; listing and starting both kinds; the
sign-in screen for a phrase or an nsec, deduped on pubkey rather than wallet
id; indexer relays and a not-found exit for the sync that today asks one
relay and never finishes; recovery for a key with no phrase; tests; rollout.

Two findings along the way are recorded as pre-existing rather than new:
loadNostrProfile(startupRoute) keys off a Profile row a placeholder account
does not have and answers Landing while observeProfile answers the sync
screen, and the library's LocalKeyManager.nostrPublicKey() returns the
33-byte compressed key, not a nostr key.

Replayed onto Mantra by docs/curated-to-mantra.md: README.md: line-set three-way merge, both sides' additions kept and this commit's deletions applied.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Pulled-From: curated/curated@daae63d5c5
2026-09-13 12:00:19 +02:00
..

mantra docs

Notes on the parts of this app whose behaviour is not recoverable by reading the code alone — where the reasoning lives in a protocol, a failure mode that is silent, or a decision that looked arbitrary and was not.

document covers
shared-key-ceremony.md ChillDKG over NIP-17: the rounds, the approval gates, the chat transcript, participant ordering
shared-key-derivation.md deriving further keys from the group's threshold key with FROST tweaks — why not BIP32, why no chain code, and the one rule that must not be broken
subgroups.md a group making another group — the four ceremonies, what the parent's signature actually covers, and why the child's key is fresh rather than derived
frost-batch-signing.md signing several events in one ceremony — why one nonce can never cover two messages, and the phased schema, wire and UI work that follows from it
marmot-membership.md how members join an MLS group, and the epoch race that makes a missing member look like a successful invite
member-chronicle.md handing a member added after the work was done the group's signed record — why the events are not on the wire at all, and why the room's id is enough to verify them
marmot-direct-messages.md a one-to-one message inside a group as a stock NIP-59 gift wrap — what its MIP-03 carve-out costs, why the sender cannot read their own, and the one query that would broadcast it
mls-skipped-keys.md why a group event that arrives a moment late is dropped for good, which flows trigger it, the quartz fix, and the partial mitigation in this app
long-running-sync.md the chat subscriptions that stay open instead of pulling once per screen — why the request queue could not simply hold one, and how the group filter follows the room list
dead-code.md code in the sync and relay stack that nothing calls, why each piece is still there, and which of it is a bug rather than a leftover
nsec-sign-in.md signing in with an existing nostr key — why an nsec can never have a wallet behind it, the ten call sites that make it small, and the sign-in machine that was already built and unreachable
jvm-target.md what desktop support cost, phased — why the native chain was already done, why an empty source set in our phoenix fork was the real blocker, and why DAO tests need none of it
material-design-conformance.md what the M3 foundations actually require, measured against all 43 screens — the colour pairing that renders the app's own proposals invisible, and eight phases that put the decisions back in the theme
curated-to-mantra.md pulling the Curated fork's thirty-nine commits back under Mantra's names — which lines of work to take, the three decisions, and a measured way to replay a twice-rebranded history without touching seven hundred files by hand

Start with the ceremony if you are new to this area; the Marmot notes all assume it. Read the skipped-keys note before debugging any "the other device never got it" report — it is silent, and it looks like every other kind of delivery failure. The sync note stands alone, and the dead-code inventory reads as a follow-up to it. The batch-signing note is a phased plan that has been built: read it after the derivation note, whose one rule is the same one it is built around. The member chronicle note is a phased plan that has not been built, and reads as the membership note's unanswered half: what a member who joins late can be given, and the one thing they cannot. The jvm-target note is unrelated to all of them: it is a build and packaging story. The subgroups note is a phased plan that has been built; it assumes both shared-key notes and reads as the ceremony's second half — what a group does once it has a key, and what it can say about a group that does not yet. The Material Design note is a phased plan that has not been built, and is the only one about what the app looks like rather than what it does; read the jvm-target note first if you want to know why its adaptive-layout phase exists. The curated-to-mantra note is a phased plan that has not been built, though its dry run has: it is about the repository rather than the app, and reads alone, except that its first decision leans on the derivation note's one rule. The nsec sign-in note is a phased plan that has not been built; it inherits the key-storage decision from the jvm-target note and drives the navigation state machine NavigationViewModel.processLocalAccount implements, so read it with the code open.