aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/names.js
Commit message (Collapse)AuthorAgeFilesLines
* Names: letters and numbers only, 2–24 — coinos v2's rule. The registrar ↵Adam Soltys5 days1-2/+10
| | | | | | | took a-z, 0-9 and . _ - (1–30), so bitcoin-education and a dozen others got through. A NEW claim must now match /^[a-z0-9]{2,24}$/ (v2's /^[\p{L}\p{N}]{2,24}$/u, held to ASCII since a name is a DNS label); a name already held (19 with . _ -, plus "f" and "g") is grandfathered — its owner can still update it — as are v2 migrations carrying their own name and npub-shaped defaults. /name/<n> answers invalid: true for a free name that breaks the rule; the claim form says "Letters and numbers only" as it's typed, and the suggested name from a nostr profile is stripped to letters and digits. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Vps2H27rhbG9ZqseGfMrc3
* Front door: a "Migrate a coinos account" button under the sign-in doors, ↵Adam Soltys6 days1-1/+7
| | | | | | opening a page that says a wallet and its twelve words come first (Create, or the sign-in doors), and /migrate on a device without a wallet opens on that page instead of an unexplained welcome; while a move is queued the recovery-phrase step offers no Later. Spending step: an account whose custom name the registrar handed back (a wallet a sign-in restored) leaves the wizard instead of being shown a claim form it could only retype its own name into — claiming it again "succeeded" onto the same page; the claim form also waits behind "Getting things ready…" until the registrar lookups settle Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Change username: a name this wallet's key claimed before a login identity ↵Adam Soltys6 days1-0/+11
| | | | | | was attached no longer reads as taken — the identity-signed claim is refused, so retry signed by the wallet key that owns the record Co-Authored-By: Claude Opus 5.5 <[email protected]>
* POS terminals ring up in the owner's currency: the app sends its currency ↵Adam Soltys6 days1-1/+4
| | | | | | when minting a terminal token (it sent none, so every terminal priced sales in USD and a $0.03 sale paid out as $0.04 CAD), and a new token retunes the terminals already paired to that name Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Send: a lightning address moves on to the amount by itselfAdam Soltys12 days1-0/+8
| | | | | | | | | | | | | - Pasted with the keyboard (not only the Paste button) it is complete text: it advances at once, as a paste always did through the button. - Typed and then left alone for 0.9s, it is checked quietly (names: our registrar or BIP-353 DNS; zaps: the LNURL-pay endpoint answers) and the form moves on only if something answers. A half-typed domain answers nothing, so it just waits, with no error; finishing it moves on. - tools/send-lnaddr-advance-test.js (live registrar/DNS, [email protected]). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Dmcrt9KyNDKVWFKnb8BREo
* Clear abandoned payments, reset profile Pay and restore native messaging BackAdam Soltys13 days1-0/+1
|
* Sending to a coinos.io name shows the person, not the ark address it became.Adam Soltys2026-09-271-3/+10
| | | | | | | | | The recipient box keeps the name, with their face beside it and "Sent instantly, no fee."; the review names them too. The ark1… the name resolved to is plumbing, and read as gibberish to anyone new to this. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
* Ark server is a setting again; an address on another server falls back to ↵Adam Soltys2026-09-221-0/+2
| | | | | | | | | | | | | | | | | | | Lightning. Settings → Advanced → Ark server: coinos, Second (ark.second.tech) or a custom server, per network — the stored choice is honoured on mainnet again. Ark state is kept per server, so switching hides but never loses coins; the card says what the current server holds and asks before letting go. After a switch the reusable address, the nostr advert and the payment name's ark= instruction follow the new server. Sends between servers can't be arkoor, so an Ark address that names a different server (its first bytes hash the server key) is treated as no Ark address at all in the pay ladder — a coinos name or npub then goes over Lightning by itself — and a pasted one is refused with the reason. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* POS token card: the terminal is flashed at coinos.io/flash.Adam Soltys2026-09-211-1/+1
| | | | | Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* Settings: the terminal's cards (POS tokens, tap-to-pay link) move to Point ↵Adam Soltys2026-09-211-8/+10
| | | | | | | of sale; the show/hide toggle is gone. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* First run: a new wallet is offered a Spending account before the home ↵Adam Soltys2026-09-211-0/+3
| | | | | | | | | | | | | screen, Not now one tap away. The wizard's spend step (claim a name, get a payment address) now follows the seed screen and the sign-in backup screen, wherever Spending can be set up (Ark-capable network with the names registrar, a signing account). Not now lands on Savings like before. namesAvailable answers 'yes'/'no' rather than a boolean, which featureHook would read as no answer. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* Point of sale: /pos, a per-device till mode, an on-screen pad — and off ↵Adam Soltys2026-09-211-2/+1
| | | | | | | | | | | | | | | the Receive tab. v3.coinos.io/pos opens the point of sale once a wallet is up (claimed at boot before any feature reads the path), so the till can be bookmarked or put on a home screen. Settings → Payments gains "Start in point of sale on this device" (localStorage, not synced: the till, not every phone the owner carries). The amount and the custom tip get a 3×4 pad that edits the same field a keyboard or a paste would. The button under the payment address on Receive is gone. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
* Point of sale: a bill, an optional tip prompt, one invoice, and a ledger ↵Adam Soltys2026-09-211-1/+2
| | | | | | | | | | | | | | | | | | that keeps tips apart. A new deferred feature (src/features/pos.js): type the amount in the display unit, optionally a note, Charge. With the tip prompt on, the customer sees the bill and picks a percentage (configurable, default 10/15/20), their own figure, or no tip; one Lightning invoice is made for the total through the Ark feature's receive (new hooks arkLnInvoice/arkLnWatch/arkLnUnwatch/ arkLnCancel wrap createLnInvoice and pollArkLn). Paid, expired and cancelled sales are recorded with the bill and the tip as separate figures, and the fiat rate at the time; the amount screen shows today's bills, tips and total. Doors: Settings → Payments card, and a button under the payment address on Receive (a receiveExtras hook the names pane renders). Co-Authored-By: Claude Fable 5.1 <[email protected]>
* Offer migration only for submitted unmigrated legacy namesAdam Soltys2026-09-111-19/+52
|
* Onboarding: fix the crash after a name claim/migration; keep a login-owned ↵Adam Soltys2026-09-101-1/+8
| | | | | | | | | | | | | | | | | | | name through signer resume. "Something broke" right after a coinos.io migration completed: the spend step advances past the avatar ask by calling nextAfterAvatar(), which was a const declared further down the same function — a temporal-dead-zone throw for any profile that already had a picture. Now a hoisted function. Also, the claimed-name ownership check only counted the LIVE login signer. A bunker/Google login resumes seconds after load, so for that window a name owned by the login identity (every migrated coinos.io name) looked foreign, was dropped, and the wallet key's npub-shaped default took its place — the address visibly flipped from [email protected] to npub…@coinos.io. The stored login pubkey now counts as ours too. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Nw1Dijik1tLVKRM1WkU7xE
* POS tools are merchant-only now: the tap-to-pay link and terminal-token ↵Adam Soltys2026-09-051-3/+11
| | | | | | | cards hide behind a merchant designation — a one-line "I'm a merchant — show point-of-sale tools" toggle at the foot of the payment-address card, swapping to "Hide point-of-sale tools" once on. The flag lives in the names feature state, so it follows the account to every device via wallet sync; regular users just see one quiet line instead of two cards of terminal plumbing Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
* The POS-link QR is itself a lightning: link — tapping it on the device ↵Adam Soltys2026-09-051-1/+7
| | | | | | | showing it hands the LNURL straight to whatever wallet owns the scheme, no scanning your own screen Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
* The POS-link card's LNURL copy button copies a lightning: URI (lowercase ↵Adam Soltys2026-09-051-1/+3
| | | | | | | bech32 with the prefix) — tappable and pasteable anywhere that registers the scheme, including our own Android app — while the QR keeps the bare uppercase form for alphanumeric-mode density Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
* Settings: lay the payment-address sections out as cards; zap settings under ↵Adam Soltys2026-09-051-57/+63
| | | | | | | | | | | | Nostr Custom name, point of sale, the terminal's tap-to-pay link, own node and own domain each get a card on Settings → Payments instead of hiding in collapsed sections. The one-tap zap amount and the CLINK zap code move to Settings → Nostr, where the other nostr settings are. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMi2Y1oKPZ3TeeFmLej47y
* morph: leave <details open> to the user; key the names settings sectionsAdam Soltys2026-09-051-6/+6
| | | | | | | | | | | | Every background repaint stripped the browser-set `open` attribute (the fresh render never carries it), collapsing expanded sections, and the positional child match handed one section's open state to its neighbour whenever the conditional zap-code section came or went. `open` on a details is now user-owned unless a render sets it, and nodes carrying data-key only patch into the same key. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMi2Y1oKPZ3TeeFmLej47y
* Point of sale: show the terminal's tap-to-pay LNURL, link and QRAdam Soltys2026-09-051-2/+18
| | | | | Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMi2Y1oKPZ3TeeFmLej47y
* Point of sale: a coinos-pos terminal works against a nameAdam Soltys2026-09-051-0/+25
| | | | | | | | | | | | | | | | | | Registrar: the owner mints a bearer POS token from Settings (NIP-98 POST /pos/token, DELETE revokes; /admin/pos/token for operators). With it the terminal gets /pos/me, rings up sales at /pos/invoice (fiat via coinos.io rates, or sats), reads /pos/payments, and holds a websocket at /pos/ws that gets a payment message when the sale settles. Sales are always minted on our node so the settle loop sees them and the ordinary forward path delivers the sats to the name's ark address. The name's lnurlp pins the newest unpaid sale under five minutes old — coinos.io's /p/<name> rule — so an NFC tap or a scan pays exactly that invoice. Wallet: a "Point of sale" section on the names card creates, copies and revokes tokens. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMi2Y1oKPZ3TeeFmLej47y
* Lightning receives to a [email protected] address now wear the ⚡ instead of ↵Adam Soltys2026-09-041-0/+18
| | | | | | | the Ark mark: a faucet paying the LN address settles on the registrar's CLN and arrives as an anonymous arkoor from the float (the mailbox protocol carries no memo), so the wallet genuinely couldn't tell the rail. The registrar now records a receipt {sat, hash, ts} per LN settlement it forwards via the float (7-day ring per name) and serves them at GET /lnreceipts (NIP-98, owner/manager only — it's a feed of incoming amounts); the wallet fetches them through the names feature (which holds the signer) and fuzzy-matches receive movements by exact amount + delivery within ±3 min, stamping viaLn + the payment hash so a receipt can never claim a second row. History row and detail view show ⚡ for viaLn receives; the tag rides the sync snapshot to other devices via merge enrichment. viaClink deliveries need none of this — the wallet's own LN-receive flow already tags itself. Best-effort by design: an amount+time collision only mislabels an icon Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
* Two small trims: the payment detail's copy-preimage becomes a full-width ↵Adam Soltys2026-09-021-6/+2
| | | | | | | button matching the Back beneath it, and the receive page's lightning address drops its edit pencil — renaming lives in the profile editor's username field, and two doors was one too many Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The migrate door opens from the username screen too: the same 'Migrate an ↵Adam Soltys2026-08-311-1/+12
| | | | | | | existing coinos account' link the wizard offers now sits under the claim form (mainnet only, address required) — a coinos.io veteran who skipped it during onboarding no longer needs a fresh account to find it Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The username claim field forgets its draft when a wallet opens: a name typed ↵Adam Soltys2026-08-301-1/+7
| | | | | | | before logout used to greet whichever account opened next on the device (the field lives in global UI state and nothing ever reset it) Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* The migration round trip stops eating its own homework: the ?migrated= ↵Adam Soltys2026-08-301-0/+4
| | | | | | | return is stashed synchronously at boot and claimed whenever the wallet actually opens (the old 1.5s one-shot silently dropped it), the wizard's 'I'm done, continue' state survives the trip to coinos.io as a persisted step, the legacy page shows the claim in progress instead of re-asking, and a finished claim advances the wizard by itself. Fresh-seed polish riding along: the spending-setup ask stops waiting out registrar round trips that only exist for restored wallets, and the header punk paints synchronously instead of after an async identity fetch Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* Pasting your own coinos name (or ark address) opens the boarding panel at ↵Adam Soltys2026-08-301-0/+4
| | | | | | | paste time, not at review: the names resolver asks the ark feature before filling the send form, a raw address paste runs the same check, and the review path still carries a typed amount into the panel — one boardOwnAddress helper serves all three doors Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
* A door where people will look for it: 'Deliver to your own node' gets its ↵Adam Soltys2026-08-291-4/+11
| | | | | | | own entry in the address's more-options menu and a section in the Settings names card — it no longer hides as an appendix behind the CLINK zap code, which returns to being just that Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* The wallet learns to read BOLT 12 for itself: offers and invoices decode ↵Adam Soltys2026-08-291-39/+62
| | | | | | | client-side, and every invoice the ASP fetches over onion messages is verified here — payment hash read from the raw TLVs, offer terms mirrored byte-for-byte, the issuer's schnorr signature checked against LDK's exact merkle construction (proven against a live CLN-signed fixture) — so no server can hand back an invoice whose preimage it already holds. Paste an lno1 or resolve a name whose record carries one and the existing HTLC pay flow carries it (captaind's Invoice enum takes lni strings natively); a name's owner may now publish their OWN node's offer in their DNS record, retiring the registrar's stand-in — senders fetch invoices straight from their node and no coinos service ever touches the money. The /lnquote fallback prices blinded paths by entry node + advertised payinfo Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* An address can point home: a name's owner may register their own CLINK offer ↵Adam Soltys2026-08-291-6/+60
| | | | | | | code and the registrar asks THEIR node for invoices — delivered there first, float as fallback, and no invoice is relayed or paid unless it demands exactly the sats owed on the right network. hal learns to pay pasted noffer1 codes through the zap flow (fixed, variable and payer-chosen pricing, amount verified before the HTLC locks). The depth advisory slims to one line — an uncooperative exit's price and a Manage link — and the new coins screen shows each vtxo's amount, expiry and arkoor depth beside what renewal costs and buys Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
* A name the registrar no longer grants is a costume: the wallet verifies its ↵Adam Soltys2026-08-281-0/+15
| | | | | | | cached name against the record's owner and manager keys each refresh, shedding stale ones (an evicted squat once lingered in the squatter's UI) — the /name endpoint now names the manager too Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The address is fetched while the key still turns in the lock: sign-in races ↵Adam Soltys2026-08-281-0/+15
| | | | | | | a registrar lookup against the seed work and seeds the name before first paint, so the Receive pane opens straight onto its QR instead of "setting up your payment address" Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The wallet arrives without ceremony: sign-in swaps screens instantly (a ↵Adam Soltys2026-08-271-0/+3
| | | | | | | one-shot no-anim flag on the handover), and the spending-setup ask holds its tongue until the name restore has settled instead of flashing while the answer is seconds away Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The chosen name outranks the placeholder everywhere: a claim can no longer ↵Adam Soltys2026-08-271-1/+23
| | | | | | | release a custom name to make room for an npub default (the race that deleted passkeyguy), sign-in asks the registrar about the login identity before reaching for a placeholder, and the registrar answers /pubkey with the name the user picked rather than whichever record is younger Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* The app arrives in movements: real ESM chunks split the bundle (entry 333KB, ↵Adam Soltys2026-08-261-1/+1
| | | | | | | shared chunks alongside, 61KB of gifts/NWC/hats deferred past first paint into slots that keep their hook seniority), the lazy scripts wear IIFE coats so their names can't collide with the page's — which is what silently broke the remote-signer button — nip98 moves out of the login module so minimal builds stop hauling backup relays, and the smoke test learns the front door's new steps while the regtest stack rises from its IBD nap Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
* A wallet keeps one name per domain, not one name total: staging and mainnet ↵Adam Soltys2026-08-181-3/+37
| | | | | | | claims stop clobbering each other, the registrar answers who-am-I per domain, and a custom name claimed on one device replaces the npub placeholder on every other Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* The claim field greets you by name: your nostr username arrives pre-filled ↵Adam Soltys2026-08-171-0/+24
| | | | | | | when the registrar confirms it's free (or already yours) — editable, never auto-claimed Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Typed names take the instant rail too: a Send button outranks the Zap for ↵Adam Soltys2026-08-171-4/+18
| | | | | | | our domains, resolving to the ark address instead of an LNURL round-trip that needs the recipient awake Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Our names get a second answer: when DNS is late the registrar speaks for its ↵Adam Soltys2026-08-171-9/+26
| | | | | | | own records, and unknown staging names say so instead of zapping a webroot that only serves HTML Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Staging names its own: mutinynet claims land at @staging.coinos.io — play ↵Adam Soltys2026-08-171-15/+19
| | | | | | | personas and their testnet addresses stop squatting the real namespace Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Mutinynet gets the full name experience: the payment-address pane, the claim ↵Adam Soltys2026-08-171-1/+6
| | | | | | | card, the re-registration — staging stops showing raw ark addresses to people who just claimed a name Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
* Username and display name go their separate ways: the handle wears a frozen ↵Adam Soltys2026-08-151-5/+8
| | | | | | | @coinos.io so it reads as address and NIP-05, renames claim before the profile publishes, and nip05 rides along with lud16 Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* A new name offers its hand to the address: saving a renamed profile proposes ↵Adam Soltys2026-08-151-0/+4
| | | | | | | the matching @coinos.io, and any rename repoints the kind-0 lightning address so zaps never chase a released name Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
* The wizard waits out a signer login; a picked recipient shows its work, and ↵Adam Soltys2026-08-081-0/+9
| | | | | | search answers from memory before the network Co-Authored-By: Claude Fable 5 <[email protected]>
* More options also points at Savings for a plain on-chain addressAdam Soltys2026-08-041-2/+7
| | | | | | | | | Not a pane of its own: a regular Bitcoin address means receiving to Savings, so the entry switches the account selector over and lets the savings receive view show its fresh address. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015QwAtBSpKvECqp1rHLHjJk
* One More-options link replaces the BOLT 12 link on ReceiveAdam Soltys2026-08-041-14/+122
| | | | | | | | | Behind it: a one-time BOLT 11 invoice (minted by the ASP), the reusable BOLT 12 offer flow, the wallet's raw ark address, and the CLINK offer code — each on its own pane so only one scannable code shows at a time. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015QwAtBSpKvECqp1rHLHjJk
* The npub default never displaces a custom nameAdam Soltys2026-08-041-1/+9
| | | | | | | | | | | adoptIdentity claimed the identity npub whenever the local name differed — and claim() releases the previous name, so a nostr login could delete the user's custom address from the registrar (it did). It now asks the registrar first and yields to any custom name. The registrar's /pubkey lookup also matches manager keys now and prefers real names over npub defaults, so restored wallets find their name again. Co-Authored-By: Claude Fable 5 <[email protected]>
* Copy joins the pencil inside the address boxAdam Soltys2026-08-041-8/+13
| | | | Co-Authored-By: Claude Fable 5 <[email protected]>
* Choosing a name gets a page of its ownAdam Soltys2026-08-041-5/+17
| | | | | | | The pencil opens a dedicated screen — no balances, no tabs — wired into the history stack like the other sub-pages. Co-Authored-By: Claude Fable 5 <[email protected]>