From 23c12ac60c47604f8458d4139c447dc2f0529f04 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 7 Jul 2026 11:43:20 +0200 Subject: [PATCH] Handoff: CLAUDE.md, AGPL-3.0 LICENSE, first-sprint plan; reconcile docs (one-key identity, Nostr, AGPL, varilla/Kew SID, blockchain nuance) --- CLAUDE.md | 58 +++++++++++++++++++++++++++++++++++++ LICENSE | 27 +++++++++++++++++ docs/design/first-sprint.md | 48 ++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 CLAUDE.md create mode 100644 LICENSE create mode 100644 docs/design/first-sprint.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..7fb2d05 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,58 @@ +# CLAUDE.md — Tanemaki + +Context for AI agents (Claude Code) working in this repo. Read this first, then [`docs/design/open-decisions.md`](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`](VISION.md) for the human explanation and [`PLAN.md`](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`](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 10–80; simple by default, depth on demand. Never build "two modes". +- **License: AGPL-3.0.** Keep new deps compatible. +- 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`](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_seeds` → `commons_core`, never the reverse.** Boundary rules in [`docs/design/core-domain-boundary.md`](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`](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`](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`](docs/design/network-trust.md) and [`docs/design/g1-integration.md`](docs/design/g1-integration.md). + +## Where things live + +- Live decision log: [`docs/design/open-decisions.md`](docs/design/open-decisions.md) — check before deciding anything. +- First code steps: [`docs/design/first-sprint.md`](docs/design/first-sprint.md). +- Prior art / valuable mockups: [`docs/mockups/`](docs/mockups/) (inventory, item, search, profile, chat — the UI spec). +- Git: bare at `~/repos/tane.git`; working clone here. Commit messages in English. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..edf520d --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Tanemaki — a local-first, decentralized app to manage and share traditional seeds. +Copyright (C) 2026 vjrj / Comunes + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +SPDX-License-Identifier: AGPL-3.0-or-later + +--------------------------------------------------------------------------- +NOTE: This file currently holds the AGPL-3.0 copyright notice. Replace this +file with the full canonical license text before publishing the repository: + + curl -o LICENSE https://www.gnu.org/licenses/agpl-3.0.txt + +(then re-add the copyright line above at the top if desired). Tracked as a +step in docs/design/first-sprint.md. +--------------------------------------------------------------------------- diff --git a/docs/design/first-sprint.md b/docs/design/first-sprint.md new file mode 100644 index 0000000..95ff92a --- /dev/null +++ b/docs/design/first-sprint.md @@ -0,0 +1,48 @@ +# Tanemaki — Primer sprint (Fase 1: inventario) + +*Guía de arranque para desarrollar en **Claude Code** (en la máquina, donde Flutter corre y git funciona). Objetivo: un **inventario usable, offline y cifrado**. Nada de capa social todavía. Convenciones y decisiones en [`../../CLAUDE.md`](../../CLAUDE.md) y [`open-decisions.md`](open-decisions.md).* + +## Definición de "hecho" del sprint + +Una persona puede: abrir la app, **añadir una semilla en 20 s** (etiqueta + foto + cantidad), verla en una lista por categorías, abrir su ficha, editarla con campos avanzados plegados, y que **todo persista cifrado** entre reinicios. Multilingüe (al menos ES/EN). Corre en un dispositivo/emulador real. + +## Pasos + +0. **Prerequisitos (máquina):** Flutter SDK actualizado, un emulador o dispositivo. Quitar los locks del bare si hiciera falta (`rm -f ~/repos/tane.git/*.lock`). + +1. **Scaffolding del workspace** (`pub workspaces`): + - `pubspec.yaml` raíz con `workspace:` listando `packages/commons_core` y `apps/app_seeds`. + - `packages/commons_core`: paquete Dart puro (sin Flutter aún) — de momento casi vacío, solo la estructura y un TODO; **no** meter capa social todavía. + - `apps/app_seeds`: `flutter create` con `--org org.comunes --project-name tane` (applicationId `org.comunes.tane`). + +2. **Base de datos (Drift + SQLCipher):** + - Añadir `drift`, `drift_flutter`/`sqlite3`, y cifrado vía `sqlcipher_flutter_libs`. + - Definir tablas de la Fase 1 desde [`data-model.md`](data-model.md): `Variety`, `Lot`, `Movement`, `Species`, `SpeciesCommonName`, `VarietyVernacularName`, `Attachment`, `ExternalLink`, `GerminationTest`. Columnas comunes (UUIDv7, `created_at`, HLC `updated_at`, `last_author`, `is_deleted`, `schema_row_version`). + - `schemaVersion = 1`. Exportar esquema a `drift_schemas/drift_schema_v1.json`. Dejar el andamio de migraciones step-by-step + test de migración. + - Tipo `Quantity` compartido (kind + amount? + label); `quantity_kind` como enum estable (`pod`, `cob`, `head`, `packet`, `handful`, `grams`, `count`…), etiqueta localizada. + +3. **Identidad y cifrado (mínimo para la Fase 1):** + - Generar una **semilla raíz** (compatible Duniter; curva a confirmar) al primer arranque; guardarla en el almacén del sistema. Todavía sin red. + - Llave simétrica de la BD en el keystore; abrir la BD cifrada con ella. **Nada en claro en disco.** + - (La derivación secp256k1/Nostr y el QR de recuperación pueden ser historias posteriores del sprint, pero deja el hueco en el diseño de identidad.) + +4. **i18n:** configurar `flutter_localizations` + `intl` (o `slang`). **Ninguna cadena hardcodeada.** Arrancar con ES y EN. + +5. **UI del inventario** (spec = mockups en [`../mockups/`](../mockups/)): + - **Lista de inventario** (`06_inventory`): ítems por categoría, con foto/inicial, buscar. + - **Alta rápida**: etiqueta + foto (cámara) + cantidad cualitativa. 20 segundos. Resto plegado ("Añadir más…"). + - **Ficha de ítem** (`07_inventory_item`) con pestañas y **edición** (`071`): nombres (propio/vernáculos/científico opcional autocompletado del catálogo), lotes (año + unidad), notas, enlaces, adjuntos. + - Progressive disclosure en todo: solo `label` obligatorio. + - Accesibilidad: objetivos grandes, tipografía grande, icono + palabra. + +6. **Catálogo de especies (semilla del bundle):** empezar con un CSV/JSON pequeño curado (unas pocas hortícolas ibéricas) con `scientific_name` + `wikidata_qid` + `gbif_key` + nombres comunes ES/EN, para probar el autocompletado. La "varilla" y Kew SID vienen después. + +7. **Verificación:** `flutter analyze` limpio, `flutter test` (incl. test de migración), y arrancar en dispositivo. Añadir el texto canónico de la licencia: `curl -o LICENSE https://www.gnu.org/licenses/agpl-3.0.txt`. + +## Fuera de alcance de este sprint (no hacer) + +Ofertas, mensajería, relays, Nostr, red de confianza, Ğ1, sincronización entre dispositivos, backup completo (más allá de dejar el formato pensado), reconocimiento por foto. Todo eso es Bloque 2 / fases posteriores. + +## Orden sugerido de historias + +1 → 2 → 4 → 5 (lista + alta rápida) → 3 (cifrado) → 5 (ficha/edición) → 6 (catálogo) → 7 (verificación). El cifrado (3) puede ir antes si se prefiere no reescribir la apertura de la BD después.