Handoff: CLAUDE.md, AGPL-3.0 LICENSE, first-sprint plan; reconcile docs (one-key identity, Nostr, AGPL, varilla/Kew SID, blockchain nuance)
This commit is contained in:
parent
465bef8691
commit
23c12ac60c
3 changed files with 133 additions and 0 deletions
58
CLAUDE.md
Normal file
58
CLAUDE.md
Normal file
|
|
@ -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.
|
||||||
27
LICENSE
Normal file
27
LICENSE
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
Tanemaki — a local-first, decentralized app to manage and share traditional seeds.
|
||||||
|
Copyright (C) 2026 vjrj / Comunes <vjrj@comunes.org>
|
||||||
|
|
||||||
|
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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
48
docs/design/first-sprint.md
Normal file
48
docs/design/first-sprint.md
Normal file
|
|
@ -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.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue