The sweep (main's item 1): 199 tracked text files, 783 lines. The founder's full name, first name and possessive become "the founder" (sentence starts capitalised); the lowercase operating-system user name in WSL paths and commands becomes <user>; the second owner login becomes "the second owner login"; the three earlier businesses and the two other brands become "the other business", "the earlier entity", "the earlier business" and "another brand"; the Chrome profile rule names the igneum.network profile, not the profile's label. The standing commit login igneum-labs is not a founder term here: the fresh-repository step renames it in the history (docs/plans/history-rewrite.md, tools/repo/fresh-repo.sh). The patterns never appear in plain text in the tree (a plaintext list would be the hit): tools/ci/founder-strings.b64 (perl regex, tab, a sample per row) is read by tools/ci/founder-strings-check.sh (every tracked text file, perl, known-failed first: the self-test plants each row's sample in a fixture and the hit must name the file), by tools/community/discord-hooks.mjs (the guard's founder and business rows; the test takes its fixtures from the samples) and by tools/repo/fresh-repo.sh (the business names of the rewrite rules). site/forbidden-strings.txt carries the same patterns as b64: lines, decoded case-insensitive by site/scrub.mjs and tools/ci/launch-gates-check.mjs (whose fixture now plants an encoded made-up name). The check runs in the gate's tree checks on every merge. Not in this commit, by main's word: the 105 commit messages and 40 personal-identity commits that need the history rewrite (listed, not run), and the secrets found by gitleaks over the history (reported with owners). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
21 KiB
Igneum phone app: the light-client wallet for iOS and Android
Design version 0.1, 3 October 2026. Status: Designed. Nothing is built. The app is the light client of docs/spec/10-light-client.md with a wallet, a miner monitor and the live network view on top. It mines nothing, holds no vote key, and asks for nothing from anyone but the user. The permanent line of spec 8.5 item 3 appears on every screen that mentions a seed, a key or support, verbatim:
Nobody from Igneum will ever ask for your seed.
Decisions in one table
| Id | Decision | Section |
|---|---|---|
| A1 | No mining on the device, no remote-mining control that starts or stops rigs from the app in version 1; the app reads | 1 |
| A2 | The chain is verified by the section 10 engine in checkpoint mode; a balance is shown with its status (executed, proven, locked) and the engine's own status (voter set from nodes, or verified) | 2 |
| A3 | Keys live in the platform's hardware-backed store; the seed is a 24-word BIP-39 phrase shown once, confirmed by re-entry, never uploaded, never typed anywhere in the app except the restore screen; hardware wallets over Bluetooth in a later version | 3 |
| A4 | Miner monitoring is read-only over the pool protocol's stats message (spec 9.5) or the user's own node's RPC, authorised by a node card the desktop app shows as a QR code |
4, 5 |
| A5 | The live network view shows the same data as site/live.html, taken from the app's own light client where the engine can verify it and from the observer feed where it cannot, each labelled |
6 |
| A6 | One Rust engine (light client, wallet signing, pool-protocol client) shared by the phone app, the browser card and the desktop app, through a foreign-function layer | 7 |
| A7 | Store release only from the public testnet (journey phase 5), on testnet coins; mainnet in the same app at phase 6 | 9 |
1. What the stores allow, as far as this document knows
Store rules from memory, approximate, to be re-read at submission:
| Store | Rule, approximate | What it means for this app |
|---|---|---|
| Apple App Store Review Guidelines, 2.4.2 | Apps may not run unrelated background processes such as cryptocurrency mining and should not drain the battery or strain the device | No hashing on the phone, ever; the light client's BLS and proof checks are brief and foreground |
| Apple, 3.1.5 (b), cryptocurrencies | Wallet apps may store and transfer virtual currency when the developer is enrolled as an organisation; apps may not mine on the device; apps may facilitate mining performed off device; exchanges only from the exchange itself; no token offerings | The developer account is an organisation (section 10); the app is a wallet and a monitor; it sells nothing and lists no exchange |
| Google Play, financial services policy | Apps that mine cryptocurrency on devices are not allowed; apps that remotely manage mining are allowed | Same posture; remote management is still left out of version 1 (A1) so that the app's only write path is a signed transaction the user sends |
| Both stores | Financial apps need clear disclosure, a privacy policy, and no misleading claims | The verification status is shown as the engine computes it (spec 10.8 wording), never "verified" without a check having run |
The last row is the honest-sentence rule applied to a screen: the app shows "voter set from nodes" until phase two, exactly as the homepage card does.
2. Verify the chain
The engine runs spec 10 in checkpoint mode: trusted checkpoint and seed list compiled into the build, headers and certificates per checkpoint, the latest wrapped proof, eth_getProof for every balance. Per day about 3.4 MB at 1,000 voters (spec 10.5, Designed, approximate), on Wi-Fi or cellular at the user's choice, with "proof on demand" as the low-data setting (2.3 MB a day).
The Verify screen shows: the latest certified checkpoint and its age; the signed weight as a fraction of total; the latest proven segment and its distance behind the checkpoint; the proof system version; bytes fetched today; the voter-set status ("from 3 of 5 nodes" or, from phase two, "verified"); the nodes in use and their identity keys; and the last failure, if any, in the words of spec 10.8 item 7.
Full-header mode (spec 10.4 item 6, the lottery verified on the phone) is not in version 1; it depends on O-10.4.
3. The wallet
| Item | Decision | Label |
|---|---|---|
| Key storage | iOS Secure Enclave through the Keychain with device-only, biometric-gated access; Android Keystore with StrongBox when the device has it, else TEE-backed. The signing key for an EVM transaction is secp256k1, which the enclaves do not sign natively, so the private key is wrapped by an enclave key and unwrapped into memory only for the duration of one signature (approximate: the common pattern on both platforms) | Designed |
| Seed | BIP-39, 24 words, generated on device; shown once, confirmed by re-entering words in random positions (spec 8.5 item 1's rule for the desktop app, applied here); optional second confirmation after 24 hours | Designed |
| Derivation | BIP-44 path m/44'/coin'/0'/0/n with Igneum's SLIP-44 coin type; the coin type is unregistered (Open, P1 below) and the app uses Ethereum's 60 until it is, so a seed restored into any Ethereum wallet shows the same addresses |
Designed, Open |
| Address | 20-byte EVM address, chain id 4461 / 4462 / 4463 (spec 7.4), EIP-155 signatures, transaction types 0, 1, 2 (design document, execution layer, 1.1) | Designed |
| Gas | One gas limit and one price, as the node quotes them with proving gas folded in (spec 7.1, "quoted gas price"); the app shows the quote and never lets a user set a limit below the estimate | Designed |
| Status line | Every transaction shows executed, proven, locked as igneum_getTransactionStatus reports them, with the app's own verification state beside it: "locked" is shown only when the engine has verified the certificate that covers the block |
Designed |
| Backup | None by the project. The app offers no cloud backup of the seed and refuses the platform's automatic keychain sync for the wallet entries; the user writes the words down | Designed (spec 8.5 item 3) |
| Hardware wallet | Version 2: Ledger over Bluetooth with the Ethereum app's signing flow (approximate), the phone as the light client and the device as the signer; the desktop app's "hardware wallet as the destination for earnings" (spec 8.5 item 2) then has a phone counterpart | Designed, later |
| Restore | The only screen that accepts a seed. It shows the permanent line above the input, refuses paste from the clipboard by default (the user can enable it), and clears the clipboard after a paste | Designed |
| The line | "Nobody from Igneum will ever ask for your seed." on the seed screen, the restore screen, the settings screen, the support screen and the store listing | Decided (spec 8.5 item 3) |
What the wallet does not do: no in-app purchase of IGN, no swap, no fiat on-ramp, no price feed in version 1 (a price needs a listing, and listings are not sought before launch, ledger X8), no staking because there is no stake (spec 5.6), no vote key (spec 8.5 item 4: the vote key is a mining key and lives with the miner).
4. Watch your own miners
Read-only. The user adds a source and the app polls it:
| Source | Protocol | What the app reads | Trust |
|---|---|---|---|
| A pool the user mines on | The pool protocol over TLS (spec 9.3), a hello, authorize with a read-only token the pool issued to the user (not the vote key: the phone never holds it), then stats and votes_carried |
Hashrate per worker, shares and their weight (spec 9.8), estimated and paid earnings in the pool's scheme, the pool's vote_mode and share_scheme, the carriage ratio of spec 9.7 item 6 for the user's key |
The pool's word for pool-side numbers; the chain's word for blocks found under the user's key, which the engine can verify from headers it fetches |
| The user's own node | The node's RPC with the read-only token from the node card (section 5) | getFinalityWeights for the user's key: blocks in the window, weight, participation, stripped-until; the miner's status lines; the node card's health fields (state, blocks, peers, blocks per second) |
The user's own machine |
| The chain alone | The light client | Blocks whose header names the user's key hash, from headers the engine fetches; coinbase payouts to the user's address from eth_getProof on the balance |
Verified |
The Miners screen shows one card per rig as the Windows app's dashboard does (one card per GPU: hash rate in big digits, blocks found; proto-cuda/windows-app/README.txt), one card for the key (weight, participation, dust warning under 100 blocks in the window, spec 3.1 W3), and one line per pool with its mode and carriage ratio. A pool in custodial mode (spec 9.6 item 5) is shown with a warning, and a carriage ratio below the O-9.6 threshold with another.
The app changes nothing on the rig. Start, stop, pool switching and overclocks stay on the desktop app and the mining OS. This keeps the app's only side effect a signed transaction (A1) and keeps the store review simple.
4.1 What the Miners screen must show
Rules from the external review of 3 October 2026 (ledger X17, O-8.2). They bind the phone's display; the desktop client carries the same rules in O-8.2 and the isolation design in O-8.3.
| Rule | Display |
|---|---|
| Net earnings | Per card and per day, after an electricity tariff the user enters in Settings; the gross beside it; "estimate" until the pool or the chain has paid |
| Two incomes | Mining income (coinbase under the user's key) and proving income (proof records naming the user's prover key) in separate columns, never summed into one number without both parts visible |
| Failed jobs | Every failed or retried shard or job the pool or node reports, with its reason, as a list the user can open |
| Release state | The rig's running release and its hash, and any pending release the user has not accepted (spec 8.2 item 4), read from the node card's status lines |
| Isolation | The phone holds no proving job and no key; the Miners screen states that the desktop prover runs apart from the wallet (O-8.3) |
| States | Everywhere the app shows a transaction it uses the four words of docs/design/execution-layer.md 2.4 (included, executed, proven, finalised); the three-word status line of section 3 becomes four, and "finality not active" replaces finalised while spec 3.9's flag is false |
5. The node card
The desktop app's dashboard already draws a NODE card (state, blocks, headers, blue score, peers, blocks per second, difficulty direction, uptime; proto-cuda/windows-app/README.txt item 2). This design gives the card a "Show on phone" action that renders a QR code, and the phone app a scanner that reads it. The desktop side is Designed and not in the launcher today.
Card payload, one JSON object in the QR, under 1 KB:
| Field | Meaning |
|---|---|
v |
Card format version, 1 |
chain_id |
4461 / 4462 / 4463 |
name |
The machine's name as the launcher shows it |
rpc |
The node's RPC address for the phone: wss://host:port or tcp://ip:port; the launcher fills in the LAN address and the user may edit it to a public one |
node_key |
The node's identity key (spec 10.6 item 1), so the phone pins the node and ignores a certificate for the name |
token |
A read-only token the node mints for this card; it unlocks the miner's status lines and nothing else, and chain reads need no token (spec 10.7) |
vote_key_hash |
The operator's key hash, so the Miners screen knows which blocks are the user's |
pools |
Optional: the pools the rig mines on, as addresses, so the app can offer to add them |
expires |
DAA score after which the token is dead; the launcher re-issues on request |
The card carries no secret key, no seed and no payout key. Scanning it on a phone that belongs to someone else gives that phone read access to one node's miner statistics until expires, which is why the launcher shows the card only on a click and the node lets the user revoke a token from the dashboard.
6. The live network
The same panels as site/live.html (status, network, blocks per second over 60 s, blue score, difficulty, hash-rate estimate, miners active in 10 minutes, peers, the block DAG, miners in the last 10 minutes, events, blocks per minute over the last hour) and the finality panel (checkpoints and the newest lock), with one rule: a number the engine can verify comes from the engine, a number it cannot comes from the observer feed (site/api/live.mjs, GET /api/live), and each panel says which. The engine can verify: the latest certified checkpoint, its signed weight, the chain's blocks per second over the headers it holds, and any block it fetched. It cannot verify: the observer's hash-rate estimate, miner counts, the events list and anything about mempools, because those are one observer's reading of its own node. The DAG picture is drawn from headers the engine holds; the homepage's simulated preview is never shown in the app.
7. The engine and the API it needs
One Rust crate, igneum-light, holds the light client (spec 10), the wallet's transaction building and signing, the pool-protocol client (spec 9, member role without the signer: it never holds a vote key), and the node-card parser. It is exposed to Swift and Kotlin through a foreign-function layer (UniFFI is the candidate, approximate), compiled to WebAssembly for the homepage card (spec 10.8), and linked by the desktop app for its own wallet screens, so that one code path produces every verification result the project shows anywhere.
What the app needs from a node is the read-only table of spec 10.7. The app adds nothing to it: wallet reads are eth_getProof, eth_getBalance, eth_call, eth_estimateGas, eth_gasPrice, eth_getTransactionCount and eth_sendRawTransaction (design document, execution layer, 8.2), status is igneum_getTransactionStatus, and the miner monitor is getFinalityWeights plus the launcher's status lines behind the node-card token. Everything the app sends to a node is a signed transaction; every other message is a read.
What the app needs from a pool is hello, authorize with a read token, stats, votes_carried and bye (spec 9.5). A pool that does not serve read tokens is shown as "no monitor", and the chain-alone row of section 4 still works.
8. What the app verifies about itself
Spec 8 binds the desktop client: reproducible builds, the release key in genesis, no silent updates. A store build cannot meet all of it:
| Rule of spec 8 | On the phone | Label |
|---|---|---|
| Reproducible build with the hash in the repository | Android: the APK can be reproducible and the repository carries its hash. iOS: Apple re-signs and may re-encrypt the binary it distributes, so byte reproducibility against the store build is not available (approximate); the repository carries the hash of the submitted archive instead | Designed, Open (P2) |
| Signed by the release key | The store signs the binary; the release key signs the archive hash the repository publishes, and the app shows its build hash on the About screen next to the published one for the user to compare | Designed |
| No silent updates | Store auto-updates are the platform's, not the app's; the app cannot refuse them. The app refuses nothing and changes nothing by itself: no remote configuration, no feature flags fetched from a server, no code loaded at run time, so a store update is the only way its behaviour changes and that update is visible in the store's history | Designed |
| The client cannot change consensus | The app signals nothing and mines nothing; nothing to bind | |
| Official sources | The two stores plus the APK on the project's domain with its hash beside the button (spec 8.4 item 2 names the domain and the repository as the only sources; the stores are added as official sources for this app only, and the spec gains that sentence at its next MINOR step, P3) | Designed |
9. Screens
- Welcome. What the app does, the permanent line, two buttons: "Verify the chain" (no wallet needed) and "Create or restore a wallet".
- Home. Balance with its status word (executed, proven, locked), the verification badge from the engine, last transactions, a line for miners if any are configured.
- Send. Address, amount, the quoted price, the status words explained in one line each, biometric confirmation.
- Receive. Address and QR.
- Activity. Transactions with the three status flags and the checkpoint that locked each.
- Verify. Everything in section 2.
- Network. Everything in section 6.
- Miners. Everything in section 4; add a source by scanning a node card or entering a pool.
- Scan. The node-card scanner.
- Settings. Network (testnet or mainnet), data mode, nodes (the seed list, the user's own), the hardware wallet (version 2), About with the build hash.
- Seed. Shown once at creation; confirmation by re-entry.
- Restore. The one screen that accepts words.
- Support. The official sources, the hash, the line, and no chat: support never asks for anything.
10. Build plan, tied to site/journey.json
| Journey phase | What ships | Gate for the app |
|---|---|---|
| Phase 3, devnet (started 3 Oct 2026, 20 nodes by Mar 2027) | igneum-light reads the devnet: checkpoint headers, certificates, voter set from nodes; no proofs yet (the devnet has no execution layer); the Network and Verify screens on an internal build; the node-card QR added to the Windows launcher's NODE card |
Certificates verified on a phone against the devnet; O-10.1's byte counts recorded; O-10.3's BLS timings recorded |
| Phase 4, finality and job market (Apr to Jul 2027) | The Miners screen over the reference pool of spec 9 (O-9.1); the wallet on devnet coins behind an internal flag; the carriage ratio of spec 9.7 item 6 computed on the phone | The pool protocol's O-9.5 and O-9.6 measurements; the eclipse re-run of O-10.5 with the phone as the client |
| Phase 5, public testnet (Aug to Oct 2027) | Store submission on both platforms with testnet coins only; the homepage card switched from PREVIEW to the testnet build of the same engine (spec 10.8); the wrapped proof verified once R4 (ledger P3) has run | Both stores approve a build that mines nothing; the card's steps 1 to 7 run in a browser; 1,000-miner gate data from the Miners screen is not used, because X5's independence definition is a separate measurement |
| Phase 6, mainnet fair launch (Nov 2027) | Mainnet selectable in the same app; the trusted checkpoint for mainnet shipped in the first release after the first certificate (spec 3.8's first month means no certificate before day 30, so the mainnet client runs on the finality-depth bound until then and says so) | The app shows "finality not active" for the first month, as the exchange guidance of spec 3.9 requires |
| Phase two of the proof system (after mainnet, design document section 7) | The consensus proof replaces the voter set from nodes; the "from nodes" status disappears from every screen and the card | O-10.8 |
No durations for the engineering are given here beyond the journey's phase dates; the work is tied to those gates, not to a calendar of its own.
11. Open items
| Id | Item | What closes it |
|---|---|---|
| P1 | The SLIP-44 coin type is unregistered; the app uses 60 meanwhile, which makes Igneum addresses collide with Ethereum addresses from the same seed (a convenience for users and a footgun for anyone who sends IGN to an Ethereum-only wallet) | Register a coin type before the public testnet and decide whether to keep 60 for compatibility; owner: execution engineer |
| P2 | iOS store builds are not byte-reproducible against the repository | Decide what the About screen compares (the archive hash, signed by the release key) and write the sentence into spec 8 at its next MINOR step |
| P3 | Spec 8.4 item 2 names the domain and the repository as the only official sources; the stores are a third for this app | Spec 8 MINOR step |
| P4 | The read-only token format for pools and node cards, and its revocation | Define with the reference pool of O-9.1; the node card's expires field is the first version |
| P5 | Remote management of rigs from the phone (start, stop, switch pool) was left out of version 1 for store simplicity and to keep the app's only write a signed transaction | Revisit at phase 5 after both stores have approved version 1 |
| P6 | Hardware wallets over Bluetooth | Version 2, after a device vendor's Igneum chain id support, which needs the chain id registered on ethereum-lists/chains (spec 7.1) |
| P7 | The developer entity shown on the store listing | Section 12 |
| P8 | The display rules of 4.1 need fields the pool protocol's stats and the node card do not yet carry (the tariff is local; failed jobs, release state and proving income need fields) |
Add the fields with O-9.5 and node card version 2; O-8.2 |
12. The decision for the founder
Both stores show the developer's legal name on the listing, and Apple's wallet rule (3.1.5 (b), approximate) wants an organisation account, not an individual. CLAUDE.md's standing rule is that the organisation owner is never publicly visible. A store listing cannot honour that rule: some entity's name will be on the page. The decision is which entity publishes the app (an existing company, a new one for Igneum, or a foundation that does not yet exist), which also decides the privacy policy's signatory and the release-key steward's relation to it (spec 8.2 item 2, O-8.1). Nothing in sections 1 to 11 depends on the choice, and nothing can be submitted to a store without it.