1
0
forked from GRIN/grim

12 Commits

Author SHA1 Message Date
2ro e623271476 locales: add Traditional Chinese (zh-TW)
Full native-quality Traditional Chinese (Taiwan) locale covering all 910
keys. Shared GRIM-inherited keys use jasperli2026's zh-TC values verbatim;
goblin.* namespace translated from the corrected Simplified source into
Taiwan-idiom Traditional (OpenCC s2twp plus a manual Taiwan post-fix and
review pass), keeping Jasper's voice and crypto-wallet register. Cangjie
keyboard labels reused from zh-CN; lang_name set to 繁體中文.

Wired into the i18n drift test (OTHER_LOCALES) and README attribution;
rust_i18n auto-loads it and the language picker labels it via lang_name.
System locale zh-TW auto-selects; news folds zh-TW to zh (shared with
Simplified) as noted in news_locale_code.
2026-07-08 02:22:53 -04:00
2ro 78c5667a18 Add Japanese (ja) as ninth Goblin wallet locale
Full translation of all 918 goblin.* leaf keys from en.yml, byte-matching
key order and %{...} placeholders, standard polite desu/masu register.
House terms follow the es/ko precedent: Goblin/GoblinPay/GRIM/Tor/Nostr/
slatepack/npub/nsec stay untranslated; wallet = ウォレット, recovery
phrase = リカバリーフレーズ, identity = アイデンティティ, relay = リレー,
handle stays as a katakana loanword (ハンドル) throughout.

Font: verified glyph-by-glyph against fonts/noto_sc_reg.otf (already
wired into every font family stack) that it covers every character used
in ja.yml, including hiragana/katakana and kokuji kanji not used in
Chinese, so no new Japanese font file is needed.

Keyboard block keeps literal QWERTY romaji like en/es/fr/de: the custom
on-screen keyboard widget is dead code in this fork (no_soft_keyboard is
always true; native OS keyboards handle all text entry), so there is no
functional need for a kana layout, per zh-CN precedent review.

Registers ja in tests/i18n_keys.rs OTHER_LOCALES and refreshes locale
count/list comments in src/lib.rs, src/gui/views/goblin/mod.rs and
src/gui/views/goblin/data.rs.
2026-07-07 01:49:48 -04:00
2ro 773589a2f1 Add Spanish and Korean locales (es, ko)
Translates every en.yml key into es.yml and ko.yml (918 keys each,
placeholder-parity verified), wires both into the drift/call-site test
(tests/i18n_keys.rs), and bundles a Hangul font subset (noto_kr_reg.otf,
~1.9MB, Noto Sans CJK KR Regular subset to Hangul + Jamo + Latin/CJK
punctuation) as a proportional/monospace fallback so Korean UI text
actually renders instead of showing tofu boxes. The Chinese font already
covers Han but not Hangul, which is a disjoint Unicode block.

Language registration itself needed no code changes: rust_i18n::i18n!
auto-discovers yml files in locales/, the locale-detection fallback in
setup_i18n already matches on bare subtags generically, and the language
picker iterates rust_i18n::available_locales!() and renders each
locale's own lang_name key (Espanol, and Hangul for Korean).
2026-07-06 23:09:45 -04:00
2ro d24a09074a goblin: polish FR stale label + fix raw-key leaks on this branch
FR wallets.tx_stale was 'En attente trop longtemps' (noun + adverb, not
grammatical); now 'En attente trop longue', adjective agreeing with attente.
Other five locales for tx_stale / receipt.stale_note read natural, left as-is.

Also carries the two raw-key leak fixes (goblin.receipt.copied ->
goblin.receive.copied, wallets.canceled -> wallets.tx_canceled) and the
every_t_call_site_key_exists_in_en guard so this branch is clean standalone.
2026-07-06 22:09:05 -04:00
2ro 1f36631777 Goblin: retire Nym from the public toolchains + drop internal test harnesses
- CI (release.yml/build.yml): remove fetch-nym + AWS_LC_SYS_PREBUILT_NASM;
  the default cargo build --release is Tor/arti only now (nip44 fetch kept).
- Cargo.toml: nym-sdk is optional behind the `nym` feature so the default
  build never pulls it.
- Delete the dead Nym-era probes (xrelay_smoke, connect_timing,
  tunnel_measure) that referenced the removed Nym API and broke `cargo test`.
- Untrack the internal E2E harnesses (e2e.rs, nostr_e2e.rs) via .gitignore;
  gate `mod e2e` behind the `e2e-internal` feature so clones still compile.
- Refresh stale Nym comments in build.rs and the build scripts.
2026-07-04 05:59:56 -04:00
2ro c701f0f480 Floonet scoped Nym exit + NIP-44 v3 + wallet polish
Money path:
- Scoped, unbonded Nym exit for the money-path relay: the wallet dials a
  relay operator's co-located exit over a MixnetStream (src/nym/streamexit.rs)
  which pipes to its one relay; hostname-validated TLS end to end, no public
  DNS. Anchor + fallback (never pin-only): any exit failure degrades to the
  smolmix tunnel. relay.goblin.st's exit address is pinned in the relay pool
  (src/nostr/pool.rs) and the maintainer gist so it bootstraps offline.
- STREAM_SETTLE bridges the open-before-accept gap so the first TLS byte is
  not dropped into a stalled handshake.
- Verified end to end: two wallets complete a real gift-wrapped Grin payment
  through relay.goblin.st over the exit, finalized + posted on mainnet
  (src/wallet/e2e.rs, ignored live test).

Encryption:
- Adopt NIP-44 v3 for the NIP-17 gift-wrap path (G4): src/nostr/wrapv3.rs,
  nip44 path dep; v3<->v3 and v3->v2 interop.

Also: mix-DNS (src/nym/dns.rs), full localization pass, GUI polish,
avatar-ring example, Android icon/script updates, GRIM deviation notes,
xrelay + connect-timing tests.
2026-07-02 04:17:59 -04:00
2ro f0b854171c Build 78: honest transport labels, request decline/cancel, NIP-05 on requests, full localization
Settings now says "Manual transaction" and the privacy row reads "Messages &
lookups" opening a new Network privacy page that tells the truth: messages,
names, price and avatars ride the Nym mixnet; the grin node connects directly.
README and lander updated to match.

Requests are messages, payments are final: declining a request now sends the
requester a void control message (NIP-17), a requester can cancel a request they
sent (cancels the local invoice and notifies the payer), and incoming requests
resolve the sender's verified @username instead of a bare npub. The Requested
amount on the success screen is centered. New NostrDecline/NostrCancel tasks and
a goblin-action control message carry it, bound to the stored counterparty.

Localization: every Goblin-screen string moved to t!() keys (370 keys) and
translated into de/fr/ru/tr/zh-CN, guarded by a key/placeholder drift test.
System-locale auto-detect now matches region locales like zh-CN.
2026-06-14 21:44:24 -04:00
2ro 878f7728eb Build 34: harden the nostr ingest path (audit Medium items)
- N-F1: commit the wrap/rumor/slate dedup markers immediately after the
  durable receive/finalize, before the reply+sync tail, so a crash there
  can't re-trigger the action on catch-up. (grin + decide() already
  backstopped it; this closes the window cleanly.)
- N-F3: prune the processed-dedup store hourly in the heartbeat, not only
  at startup — a long-lived session could otherwise grow it unbounded
  under fresh-keypair spam since the 30-day TTL never re-applied.
- N-F2: kept Created/SendFailed in the finalize allow-set (removing them
  would strand a real send whose S1 reached the peer before we persisted
  AwaitingS2) and documented why it is not a forgery vector; added a test.
- Update replay_check e2e: a same-pubkey second register is now blocked by
  the name-change cooldown (fires before the one-name rule); accept either.

Validated: 35 lib tests + live nip17_slatepack_roundtrip + replay_check green.
2026-06-12 12:48:34 -04:00
Claude 0438d70cae Build 18: move the integrated node off the wallet list into the cog
- Remove the Node status chip from the wallet-list header; the integrated
  node now lives in the cog's settings as a status + Enable/Autorun section,
  with a "Node settings" button into the full stats/mining/tuning panel.
- Stop the desktop two-column rail from auto-docking the node beside the
  settings screen, so the node has a single home in the cog at every width
  (the full panel opens only on demand). Fixes the wide-window double-exposure.
- Prove NIP-17 payments transit the top public relays: parameterize the
  nostr e2e roundtrip and add damus.io + nos.lol proofs (3/3 green).
- Add DEVELOPING.md documenting how we iterate and test (Xwayland :2 recipe,
  Build N cadence, gui-sweep, e2e tests, live infra) — no secrets.

Verified live on :2: chip gone from the list; cog shows the node once
(single column, no left rail); "Node settings" opens the full panel on
demand. 34 lib tests green; nip17 roundtrip green over nrelay + damus + nos.lol.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 20:21:13 -04:00
Claude b1b9bd61af Build 13: hosted profile pictures, username release, claim/release UX
Identity overhaul (server changes deployed to goblin.st separately):

Avatars
- profile pictures hosted on goblin.st, tied to the username: tap the
  settings avatar → native image picker → 256px PNG uploaded over Tor
- letter avatars now use (background, ink) color pairs (8) keyed off the
  npub, and render the first ALPHANUMERIC char — never the '@'
- custom pictures shown everywhere self/contacts appear: settings card,
  home header, sidebar chip, peers strip, activity rows, send recipient
- AvatarTextures: disk cache (~/.goblin/cache/avatars) + background Tor
  fetch + egui textures loaded on the UI thread; a network/Tor failure
  is never cached as "no avatar" (would have stuck for 6h)
- nostr/avatar.rs mirrors the server's sniff→limits→orientation→crop→
  256→re-encode-PNG pipeline so uploads are small and previews instant

Username lifecycle
- rotating the key now RELEASES the username (and deletes its avatar
  server-side) instead of transferring; rotation aborts if release fails
- claim panel is one Claim button (checks then registers); registered
  state shows "Registered <name>" + a Release action behind an
  are-you-sure gate ("up for grabs the moment it's free")
- released names are immediately re-claimable (quarantine removed)

Other
- Tor::http_request_bytes: binary bodies + status code, for upload and
  avatar download (string http_request kept as a wrapper)
- settings reordered Identity-first, then Wallet
- sidebar node card is 3 lines: status / block height / host
- profile card shows the full npub when it fits, else head…tail

34 lib tests green. Live-verified on goblin.st: upload→serve (image/png,
nosniff, immutable)→5/day limit (6th 429)→release purges avatar; a real
picture for @fartmuncher22 fetched over Tor and rendered across surfaces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 12:22:41 -04:00
Claude ce1c071f3c Security hardening from adversarial audit
Wallet:
- identity.json (NIP-49 ncryptsec) now written 0600 in a 0700 dir so a local
  user can't grind the wallet password offline (+ regression test).
- Wallet password held as a ZeroingString through init_nostr so it's scrubbed
  on drop instead of lingering in a plain String for the session.
- Replaced 4 .unwrap() on re-read tx_meta with graceful guards (archive wipe
  mid-send could otherwise panic the nostr/task thread).
- Tor::http_request/post: bind the client once via let-else and propagate TLS
  builder errors, fixing a TOCTOU unwrap panic on concurrent Tor restart.

goblin-nip05d server (redeployed to goblin.st, verified live):
- One-name-per-pubkey now enforced by a partial UNIQUE index (closes the
  check-then-insert race); INSERT rows-affected==0 returns 409 not a false 201.
- NIP-98 replay protection: one-time auth event-id enforcement within the
  freshness window; tightened forward skew to +5s.
- Rate-limited the unauthenticated GET endpoints; SQLite in WAL mode.
- Verified live: replay rejected, second name for a pubkey blocked.

Audit verdict: fund-safety invariants (never auto-pay Invoice1; S2/I2
finalization bound to counterparty npub) and Tor-from-day-one all hold.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 02:13:15 -04:00
Claude 87efc8bb2d Add live e2e tests for the nostr relay and NIP-05 server
tests/nostr_e2e.rs (run with --ignored):
- nip17_slatepack_roundtrip: Alice gift-wraps a slatepack payment DM with a
  subject to Bob over wss://nrelay.us-ea.st; Bob unwraps, the seal-author ==
  sender invariant holds, the slatepack and subject extract intact.
- nip05_registration_roundtrip: registers a fresh name on goblin.st with a
  real NIP-98 signature, resolves it back to the right pubkey, releases it.

Both pass against the live deployed infrastructure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 01:54:37 -04:00