Commit graph

73 commits

Author SHA1 Message Date
993f7b37ab feat(identity): switch social identity, all from the one backup
Adds pseudonymous, switchable social identities derived from the SAME root
seed via an account index (NostrKeyDerivation.deriveFromSeed(seed, account)).
HKDF is one-way so accounts are unlinkable to the Ğ1 key; account 0 is the
original identity, byte-for-byte unchanged (no rotation for current users),
and every account regenerates from the single seed — so switching adds
nothing to back up.

- SocialAccountStore: keystore-backed active account + max created.
- Per-identity stores (chats, profile, name cache) namespaced by account
  scope (account 0 = legacy keys, no migration) so identities never mix.
- switchSocialAccount() re-derives the identity, re-scopes the stores and
  restarts the inbox listener; RestartWidget rebuilds the tree to pick up
  the new social singletons. DB/inventory untouched.
- Profile 'Your identities' switcher: list, create, switch (with a note
  that messages/contacts are kept separate per identity). i18n en/es/pt/ast.

Tests: account-indexed derivation (legacy 0 unchanged, accounts distinct
yet deterministic, negatives rejected); SocialAccountStore; per-identity
store scope isolation. Resolves the flagged 'change identity' decision
(open-decisions §B).

Known: switching resets navigation to home (full tree rebuild).
2026-07-10 20:22:24 +02:00
5741d6bde8 docs(block2): note 'change social identity' as an important pending decision
User-flagged (on-device feedback): no way to change the social identity today
(derived once from the root seed at startup). Records the two options —
pseudonymous social key (recommended) vs full root-seed reset — and the runtime
re-derivation implications, for a future round.
2026-07-10 13:41:44 +02:00
a03154030b docs(block2): lift the gate — open the social round
The de-risking spike validated the whole social happy path, so Block 2 moves
from "do NOT start" to STARTED. Records the build order (transport foundation in
commons_core first, on the vetted pure-Dart nostr lib) and marks open-decisions
D.3/D.7 as resolved by the spike.
2026-07-10 02:26:16 +02:00
d433748ab5 spike(block2): de-risk web of trust — the last big unknown
Adds TrustTransport as the third interface on the shared NostrConnection,
completing the social-layer happy path in the spike:

- WebOfTrust: pure, Flutter-free Duniter membership rule (N certs from members +
  within distance D of bootstrap referents), iterated to a fixpoint. The
  commons_core-worthy piece; TDD'd (threshold, distance cutoff, transitive
  growth, expired/revoked/self exclusion).
- NostrTrustTransport: certifications as a custom addressable kind (30777,
  keyed by issuer+subject) — certify renews, revoke replaces, certs expire.
- Trust filters spam (network-trust §2): seeds certify Alice; Eve stays
  uncertified; Bob discovers both offers and annotates authors — Alice known,
  Eve unknown — all over ONE shared connection.

Findings updated: WoT risk High -> Medium (policy/bootstrap, not feasibility);
overall scope Medium-High -> Medium — all three transport contracts now proven.
30 tests green, analyzer clean, Block 1 untouched.
2026-07-10 02:17:35 +02:00
8a81aaf442 spike(block2): de-risk NIP-17 messaging + validate shared-connection shape
Extends the Block 2 spike to attack the highest-risk unbuilt piece (private
messaging) and to prove the Q2 architecture recommendation with running code:

- NostrConnection: one shared socket+key+sign+REQ/EOSE lifecycle. Refactored
  NostrOfferTransport onto it; added NostrMessageTransport — two thin contracts
  on ONE connection (the 'one connection, three interfaces' shape).
- NIP-44 v2 encryption (secp256k1 ECDH -> ChaCha20 + HMAC, length-hiding pad).
- NIP-17/NIP-59 gift-wrap: rumor(14) -> seal(13) -> wrap(1059, ephemeral key).
  Alice->Bob DM round-trips through the relay: encrypted, sender authenticated,
  and metadata-private (relay/eavesdropper sees only ciphertext, an ephemeral
  author and the recipient p-tag — Alice stays hidden).

Findings updated: NIP-17 risk drops Medium-High -> Medium (hardening, not
feasibility); next de-risking target is the web of trust. NIP-44 not yet
vector-verified (noted). 20 tests green, analyzer clean, Block 1 untouched.
2026-07-10 02:11:54 +02:00
32ddaf1714 spike(block2): de-risk social layer — key derivation, OfferTransport, NIP-99 round-trip
Throwaway research spike (spike/ branch, outside pub workspace, no prod deps
touched). Validates the open Block 2 decisions before committing a funded round:

1. Deterministic one-way secp256k1 (Nostr) key derived from the Ğ1 root seed
   via HKDF — user still backs up ONE thing. Reproducible + signs (BIP340).
2. OfferTransport abstraction over Nostr NIP-99 (kind 30402); Offer stays
   inventory/location-agnostic, geohash coarsened on the wire (tested).
3. publish->discover-by-geohash proven end-to-end against an in-process
   hermetic mini-relay (~34ms round-trip).

Findings + risks + recommendation in docs/design/spike-block2-findings.md.
Block 1 suite untouched. 14 tests green, analyzer clean.
2026-07-10 01:57:25 +02:00
4acf227e30 chore(release): beta packaging — signing, changelog, store metadata, scale test
- Android release signing reads a gitignored key.properties, falling back
  to debug keys so contributors can still build --release.
- CHANGELOG.md (human, newest-first) + Fastlane/F-Droid metadata (en/es)
  with descriptions derived from docs/intro.md.
- docs/release.md: the by-hand build + manual smoke checklist (no CI yet).
- inventory_scale_test guards the list query against N+1 at 3000 varieties.
2026-07-09 23:10:01 +02:00
5d2b41a110 i18n: RTL smoke tests, Portuguese locale and a translation guide
- Add rtl_smoke_test covering inventory, detail (lot sheet) and settings
  under Directionality.rtl, with an Arabic label and vernacular name.
- Ship pt.i18n.json (Portuguese) as proof the locale pipeline scales beyond
  es/en; wire its language tile in Settings.
- docs/i18n.md documents the Weblate-ready flow for adding locales.
2026-07-09 23:06:49 +02:00
cf5d302cc1 test(state): cover InventoryCubit and VarietyDetailCubit; refresh block1 status doc 2026-07-09 22:03:36 +02:00
3db8ca558c docs: public intro narrative and in-app onboarding copy 2026-07-09 21:48:14 +02:00
2812c99280 feat(inventory): CSV/JSON export and JSON import with LWW reconciliation
Interchange export/import for Phase 1 (data-model §7):

- JSON: canonical, versioned envelope (formatVersion 1) with all sync
  metadata verbatim, photos embedded as base64, tombstones excluded.
  Species are re-resolved on import by scientific name (catalog ids are
  per-install). Reader tolerates unknown fields/enum values (§5.2) and
  rejects newer format versions with a clear error.
- CSV: export-only spreadsheet flatten, one row per lot, RFC 4180
  escaping, never any photo bytes.
- Import merges by UUIDv7 id in one transaction: insert-if-unknown
  preserving original stamps, last-writer-wins by packed HLC for known
  mutable rows, append-only movements; afterwards the local clock
  receiveEvent()s the newest imported stamp so it never runs behind.
- Settings gains a Backup section (export CSV/JSON, import JSON with
  confirmation); file dialogs behind a FileService interface backed by
  file_picker (MIT).
- Tests: codec round-trip and tolerance, reconciler LWW, repository
  export→import round-trip (fresh DB, idempotent re-import, newer-local
  wins, clock monotonicity, species re-resolution), backup widget flows.
2026-07-09 12:46:53 +02:00
42c16c0e3f feat(ui): Material 3 redesign, cover-photo viewer, About screen
Apply a Material 3 seed-green palette and rounded components across the
home, inventory, quick-add, quantity picker and variety-detail screens.
The full-screen photo viewer can now set any photo as the cover (via
attachment sort order) and delete after confirmation. Lot forms and
packaging surface as choice chips.

Extract About out of Settings into its own screen (app version via
package_info_plus, website link). Add es/en strings for the new lot
types, presentation, home tagline and About. Update Seedees v2 mockups.
2026-07-09 11:51:59 +02:00
3954c62aa6 feat(db): lot presentation + attachment sort order (schema v4→v5)
Expand LotType from {seed, plant} to six append-only forms (seed,
seedling, plant, tree, bulb, cutting) and add an optional Presentation
attribute (pot/tray/plug/bareRoot/rootBall) kept separate from quantity
so 'how many' and 'in what packaging' never conflate.

Add attachments.sortOrder so the cover photo is the lowest-ordered one,
enabling reordering from the full-screen viewer. Expand QuantityKind
with the new plant-aware forms.

Migrations are additive (v1→v5 all covered by migration_test); enum
values are stored by name and appended only, keeping CRDT sync safe.
2026-07-09 11:51:21 +02:00
48e9d15772 feat(ui): align inventory + detail with mockups (seed icons, green theme)
Visual pass toward docs/mockups (06 inventory, 07 item):
- Bundle the seedks icon font (chars a–k → seed pictograms: jar, packet, spoon…)
  and a SeedGlyph/QuantityKindIcon helper.
- Green app bar + pale-green canvas theme (buildTaneTheme).
- Inventory list: rounded-square photo thumbnail or green initial avatar, bold
  title, scientific-name subtitle, trailing edit pencil, styled category
  headers, rounded search field, seed-glyph empty state.
- Quantity selectors (quick-add + add-lot) show the seed pictogram + word;
  detail lot lines use the kind's glyph.
- Detail header restyled to mockup 07: category link + scientific name on the
  left, photo on the right.

watchInventory now also returns the linked species' scientific name (subtitle).
37 app tests green; seedks font verified in the Linux asset bundle.
2026-07-08 00:14:43 +02:00
d5eb2242ca docs(block1): status marker + IntelliJ run config 2026-07-07 22:14:53 +02:00
57c0eeadaf Before code 2026-07-07 13:20:00 +02:00
23c12ac60c Handoff: CLAUDE.md, AGPL-3.0 LICENSE, first-sprint plan; reconcile docs (one-key identity, Nostr, AGPL, varilla/Kew SID, blockchain nuance) 2026-07-07 11:43:20 +02:00
465bef8691 Note optional Darwin Core / GBIF / ALA biodiversity-portal bridge as a deferred, opt-in intention (open-decisions C + data-notes 3-bis), with privacy guardrails; not a phase or model change 2026-07-07 11:38:51 +02:00
e4ccffe168 Fix naming (Seedks->Tanemaki) in PLAN; reconcile data-model with core/domain boundary (Plantare->Pledge, Movement->LedgerEntry notes); fix quantity_label type nit; note social layer as one indivisible block in VISION; add seedks.ttf asset 2026-07-07 11:06:38 +02:00
8286d1fec8 Add VISION and design docs (backup/recovery, G1 integration, network trust, security/privacy, open decisions); update domain boundary and data notes 2026-07-07 10:49:44 +02:00
59beadc03c Add core/domain boundary doc; clarify lots (mixed year/unit per variety) 2026-07-07 01:49:35 +02:00
86b0c4d251 Add design docs; update README/PLAN 2026-07-07 01:28:54 +02:00
b08d384089 Initial import: mockups, visual identity, stock photos, project plan, README 2026-07-06 23:58:31 +02:00