5.4 KiB
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.labelis mandatory; every other field optional. Audience is everyone 10–80; 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_coreis pure Dart — ideal for TDD). Nothing merges without tests covering the new behavior; CI gates it. Seedocs/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. Seedocs/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_seeds → commons_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
- Live decision log:
docs/design/open-decisions.md— check before deciding anything. - First code steps:
docs/design/first-sprint.md. - Prior art / valuable mockups:
docs/mockups/(inventory, item, search, profile, chat — the UI spec). - Git: bare at
~/repos/tane.git; working clone here. Commit messages in English.