tane/CLAUDE.md
2026-07-07 13:20:00 +02:00

5.4 KiB
Raw Blame History

CLAUDE.md — Tanemaki

Context for AI agents (Claude Code) working in this repo. Read this first, then docs/design/open-decisions.md (the live decision log).

What this is

Tanemaki (種まき, "sow/scatter seeds"; short: Tane) — a local-first, decentralized app to manage and share traditional seeds. First app on a generic commons engine. Web: tanemaki.app. Package id: org.comunes.tane. See VISION.md for the human explanation and PLAN.md for the origin analysis (with a "Nota de vigencia" reconciling evolved decisions).

Golden rules (do not violate)

  • English for ALL code: identifiers, class/field/column names, comments, commit messages, branch names, and technical specs. No exceptions.
  • User-facing strings are NEVER hardcoded — always via i18n. The app is multilingual by design.
  • No plaintext at rest, ever — the inventory DB is encrypted (SQLCipher). No plaintext logs/temp/caches. See docs/design/security-privacy.md.
  • Local-first: everything works offline, no account, no central server. Online only enriches (degrades gracefully).
  • Progressive disclosure: only Variety.label is mandatory; every other field optional. Audience is everyone 1080; simple by default, depth on demand. Never build "two modes".
  • License: AGPL-3.0. Keep new deps compatible.
  • Tests, near-TDD. Every behavior is covered by automated tests (unit / widget / integration); do NOT rely on manual testing. Write tests first for domain logic (commons_core is pure Dart — ideal for TDD). Nothing merges without tests covering the new behavior; CI gates it. See docs/design/testing.md.
  • Discussion/design docs may be in Spanish; code and specs in English.

Stack & structure

  • Flutter/Dart, monorepo via pub workspaces. Target Android/iOS/desktop.
  • Drift (SQLite) + SQLCipher for the encrypted local DB. Versioned step-by-step migrations, schemas exported to drift_schemas/, migration tests in CI. See docs/design/data-model.md §5.
  • i18n from day one (e.g. flutter_localizations + intl/slang).
tane/
  pubspec.yaml            # pub workspace root
  packages/
    commons_core/         # identity, Party/Group, TrustEdge, Offer, Pledge, transport (Nostr)+CRDT+sync, geohash discovery. NO seed specifics.
  apps/
    app_seeds/            # Tanemaki: Variety/Lot/Movement/Species, germination, plant-family units, UI, i18n, commons_ui (embedded for now)

Dependency direction: app_seedscommons_core, never the reverse. Boundary rules in docs/design/core-domain-boundary.md.

Data model (decided, schemaVersion = 1)

Three levels: Variety (identity/accession) → Lot (a batch you hold: harvest_year, quantity, offer_status, germination) → Movement (append-only event log = history + provenance DAG + Plantare). Plus Species (bundled Wikidata/GBIF catalog), VernacularName, Attachment, ExternalLink, GerminationTest, Party, SeedBank, Offer, Plantare. Every mutable row: client UUIDv7, created_at, HLC updated_at, last_author, is_deleted (soft delete/tombstone), schema_row_version. CRDT: LWW scalars, OR-Set collections, grow-only Movement. Full spec: docs/design/data-model.md.

Decided schema details: Quantity is a shared value type (Lot + Movement); offer_status only on Lot; category free text prefilled from Species.family. Quantity units are plant-aware (cob/pod/ear/head…), not just kitchen units (§2.3.1). A Variety can hold multiple Lots with different years AND units at once.

Identity & crypto (decided)

  • One identity = a Duniter/Ğ1-style root seed (does profile, certifications, Ğ1). From it, deterministically derive a secp256k1 subkey for Nostr (messaging/offers) — because Duniter has no messaging. User backs up ONE thing (the seed, as a printable recovery QR).
  • At-rest DB key = a separate internal symmetric key in the OS keystore (unlocked by device biometric/PIN); NOT a user password. Backups also encrypted; key travels via the QR. See docs/design/backup-and-recovery.md.

Phasing — build order

Block 1 (NOW): Inventory. Shippable alone, useful with zero network. This is the current target. Block 2 (later): the social leap — offers + messaging + relays + web of trust — big and indivisible; needs its own round (and ideally funding). Do NOT start Block 2 now.

Social layer (for later) uses: Nostr (offers NIP-99, DMs NIP-17), Duniter-style web of trust (Duniter/Ğ1 compatible, ~5 certifications), optional Ğ1 currency (levels: price → wallet deep-link → optional WoT import). Cold-start via real Ğ1 seed groups + fairs. See docs/design/network-trust.md and docs/design/g1-integration.md.

Where things live