Documentation / Node distribution, EVM identity & sense
HiNet — Node Distribution, EVM Identity & Sense Integration
Status: [NEW spec] · identity + geobit-signing are [MVP-buildable now]; installer/auto-update + external-wallet binding are [MVP→LATER]. Refines Owner Identity & Proof-of-Personhood toward EVM + wallet-binding (unifying with the Quorumz identity core), and defines the iCore → sense.quorumz.com geobit inter-app flow.
The app is a node: a downloadable, self-updating desktop node with an owner-controlled EVM identity, whose iCore can turn a social post it reads into a signed geobit in sense.quorumz.com.
1. Two EVM keys — owner (privilege) + iCore (signer)
Unifies with Quorumz's identity core (BIP39 → EVM address; verify_evm_signature). Two keys, secp256k1/EVM:
| key | who | how it's made | where | role |
|---|---|---|---|---|
| Owner key | the human | BIP39 mnemonic generated on first run (shown once to save) or bind an existing wallet (MetaMask/Rabby) | mnemonic never stored server-side; wallet key stays in the wallet | owner privilege; the account; registration is on the owner address |
| iCore key | this node | random EVM keypair | private key encrypted by the owner (§3), stored ~/.hinet/icore_key.enc |
signs geobits + quorum receipts; owner-certified |
- Owner certifies iCore: the owner signs
{icore_address, node_id}→ anOwnerBindingproving this iCore belongs to this owner. One owner may own several iCores. - Registration (into the HiNet registry / node pool) is keyed on the owner address; the iCore address is the node's day-to-day signer.
- Ed25519
node_id(node_identity.py,[EXISTS]) stays as the self-certifying device id; the EVM keys are the economic/account identity. (Two id systems, one node: Ed25519 for device self-certification + signing the audit chain; EVM for account/ownership/geobits/payments — the layer that touches money + Quorumz.)
2. Owner: mnemonic OR bound wallet [MVP: mnemonic; LATER: wallet]
- Create (MVP):
Account.create_with_mnemonic()(eth-account, HD features) → a 12/24-word phrase + address. Show the phrase once, force "I saved it," never persist it. This is the sovereign-key backup (loss = loss). - Bind existing wallet (LATER): MetaMask/Rabby via the browser —
personal_signa HiNet challenge to prove control of the address (owner = that address; no key ever leaves the wallet). Registration + owner-certification use wallet signatures.
3. iCore key encrypted by the owner [MVP: mnemonic-derived; LATER: wallet-encrypt]
- Mnemonic owner (MVP): derive a symmetric key from the owner secret (HKDF over the owner private key) → AES-256-GCM encrypt the iCore private key →
~/.hinet/icore_key.enc. Only someone with the owner mnemonic can decrypt/authorize. - Wallet owner (LATER): MetaMask
eth_getEncryptionPublicKey→ encrypt the iCore key to it (EIP-1024 x25519-xsalsa20-poly1305); only the owner's walleteth_decryptrecovers it. The real "encrypted by your wallet." - The iCore key is loaded into memory to sign; owner privilege (rotate iCore, revoke, re-encrypt) requires the owner secret/wallet.
4. iCore → sense.quorumz.com geobit (the inter-app flow) [MVP-buildable]
When the iCore summarizes the comments on a post (LinkedIn/X/Facebook/…) into topics + sentiment, it emits a signed geobit that lands in sense.quorumz.com:
post URL ─▶ fetch (fetch_url / browser-companion / pasted text)
─▶ iCore summarizes → { summary, topics[], sentiment, comment_count, source_url }
─▶ build Geobit { body, category, tags(topics+sentiment), source_url, lat/lon?, ts }
─▶ SIGN with the iCore EVM key over the "quorumz-geobit-v1" payload (same contract as Quorumz)
─▶ POST {SENSE_API}/api/geobits/contribute (evm_address = iCore addr, signature)
─▶ appears as a geobit in sense.quorumz.com, attributed to the iCore (owner-certified)
- Reuses the Quorumz contract verbatim: geobits are already "anonymous, cryptographically signed" and
verify_evm_signature-checked ([app.py/geobits/contribute], payload tagquorumz-geobit-v1). The iCore signs exactly like a Quorumz web client — so no Quorumz API change is required; the iCore is just another signing contributor. - Attribution: the geobit is signed by the iCore address (owner-certified), so "which node summarized this" is verifiable, while the owner stays the account.
- Config:
HINETD_SENSE_API(e.g.https://api.quorumz.com); unset → the app returns the signed geobit without submitting (dev/offline). - Honest access caveat: reading a login-gated post's comments is the §PL-5/8 problem — MVP works on public/pasted content; live LinkedIn/X comment threads need the browser companion or the platform API.
5. Distribution + auto-update [MVP]
- Downloadable node from the site: a macOS installer (§6) links from
i.quorumz.com(a "Download HiNet" CTA) → the app == a node. - Auto-update: the site hosts a version manifest
i.quorumz.com/app/version.json={ version, min, url, notes, sha256 }. The app polls it on launch + daily (GET /node/update/checkcompares to its own__version__) → if newer, shows an in-app "Update available" prompt → opens the download (or, with a signed bundle, a Sparkle-style in-place update). - MVP prompt = open the download URL; in-place auto-update (Sparkle / Tauri updater) is the packaged-bundle upgrade.
6. macOS installer [MVP→LATER]
- MVP (now):
install.shbuilds/Applications/HiNet.appwrappingdesktop.sh(shipped) — installs + runs + ⌘⌃I. - Real installer (next): py2app (or Tauri bundle) → a self-contained
.app(bundled Python + deps, no repo dependency) →create-dmga signed.dmg→ codesign + notarize with an Apple Developer ID (a user-provided cert — can't be done headless) → the download the site serves. Auto-update via Sparkle (appcast = the version manifest).
7. Walkme / first-run onboarding [MVP]
An in-app first-run walkthrough (dismiss + "don't show again"): 1. What HiNet is — your iCore, a node you own. 2. Save your owner key — the mnemonic (or bind a wallet) → the account's sovereign privilege. 3. Minimal vs maximal mode — the floating quick-box (short form) ⟷ the full app; ⌘⌃I summons/hides it; ⤢ / ⤡ resize. 4. Connect Cursor — one card, point your IDE at your local iCore. 5. Summarize → geobit — paste a post, get topics + sentiment, publish it to sense as a signed geobit.
8. What this reuses vs adds
Reuses [EXISTS]: eth-account (in the app venv) for EVM keys/mnemonic/signing; the Quorumz geobit contract (/geobits/contribute, quorumz-geobit-v1, verify_evm_signature) — no Quorumz change; node_identity.py (Ed25519 device id); fetch_url + /v1/agent (summarize); the pywebview shell + install.sh. Adds [NEW]: node_wallet.py (owner mnemonic/bind + iCore EVM key encrypted-by-owner + sign_geobit); /node/wallet/*, /node/geobit/from_url, /node/update/check endpoints; version.json manifest + in-app update prompt; the walkme; the summarize→geobit UI. Later: external-wallet binding + wallet-encrypt of the iCore key; py2app/dmg/notarize + Sparkle in-place update; registration on the owner address into the registry.
9. Open decisions [OPEN]
- Geobit geo — a comment-thread summary isn't inherently geo; give geobits an optional location (post's place, owner's region, or none) — confirm with the Quorumz geobit schema (lat/lon nullable).
- iCore-signed vs owner-signed geobits — spec says iCore-signed (attribution + the owner isn't in the loop per-geobit). Confirm Quorumz accepts a non-onboarded EVM signer, or pre-register the iCore address under the owner account.
- External-wallet UX in a native shell — MetaMask/Rabby binding needs a browser context; decide deep-link vs WalletConnect vs the bundled webview.
- Notarization identity — which Apple Developer ID signs the build (a user asset).
10. Social comment-summarizer — build order + status (2026-08-24)
The iCore side is largely built; the hard, ToS-gated pieces (full comment ingestion + posting back as the owner) and the sense-side rendering are what remain. Ordered by dependency + difficulty — note "write as me" is the hardest and LAST, not first:
- Summarize from a link or pasted text → topics + main opinions + sentiment. ✅ built —
fetch_url+/node/geobit/from_url. Works on PUBLIC/pasted content today. - Sign the summary as a geobit (contributor = the iCore EVM address) + submit to sense. ✅ iCore side built (signs
quorumz-geobit-v1, POSTs/api/geobits/contribute). ⏳ sense side: add a "post-comments summary" content_type + rendering on sense.quorumz (today only generictext/mediarender); setHINETD_SENSE_API. - Draft a reply comment + approve-before-post in the app. ⏳ small add — emit a suggested reply beside the summary + an approval step.
- Read the FULL comment thread of a login-gated post (hundreds of comments). ⏳ net-new — needs the platform API (LinkedIn/X) or the browser companion (Onboarding PL-8).
fetch_urlonly reaches public/visible content. - Post the approved reply back to LinkedIn/X as the owner. ⏳ hardest, last — write OAuth + posting APIs (LinkedIn comment API is partner-gated; X API paid) + per-platform ToS. This is "comment as myself."
Why "write as me" is last, not first: it's the most ToS-fragile and access-gated capability, and everything valuable (summarize → geobit → approve) works without it. Ship the read/summarize/geobit loop first (mostly done), then comment ingestion, then write-back.