tane/docs/design/block1-status.md

117 lines
6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Block 1 — estado actual (marcador)
*Dónde estamos en el Bloque 1 (inventario offline, cifrado, multilingüe). Este
fichero es el marcador de progreso; actualízalo al avanzar. Convenciones en
[`../../CLAUDE.md`](../../CLAUDE.md) y guía del sprint en [`first-sprint.md`](first-sprint.md).*
## Hecho ✅
Arquitectura y estado (como G1nkgo pero adaptado): **`flutter_bloc` (Cubit)** con
la **BD Drift cifrada (SQLCipher) como fuente de verdad** (sin hydrated_bloc/Hive,
que dejaría texto en claro); **`get_it`**, **`go_router`**, **`slang`** (ES/EN,
JSON por locale, compatible Weblate). Ver [`../../apps/app_seeds`](../../apps/app_seeds).
- **Workspace + CI**: pub workspace (`commons_core` puro Dart + `app_seeds`),
AGPL LICENSE, `.gitlab-ci.yml` (format + analyze + test + cobertura,
instala libsqlcipher).
- **commons_core**: UUIDv7 (`IdGen`), Hybrid Logical Clock (`Hlc`), `Quantity`
(+ `QuantityKind` plant-aware), stub de semilla raíz (`IdentityService`).
- **BD**: Drift `schemaVersion=1`, 10 tablas + columnas CRDT (HLC `updated_at`,
`last_author`, tombstones); `Movement` append-only. Export
`drift_schemas/drift_schema_v1.json` + test de migración.
- **Cifrado**: SQLCipher vía executor inyectable que **se niega a abrir en claro**;
clave de BD + semilla raíz en el keystore (secretos separados). Test
"no plaintext at rest" **verificado** (corre con libsqlcipher; en CI se instala).
- **Inventario (UI)**: alta rápida (etiqueta + foto + cantidad ~20 s), lista por
categorías con búsqueda y **miniatura de foto**/inicial, ficha con nombre
científico, categoría, nombres vernáculos (solo lectura), notas, lotes
(año + unidad) y **% de germinación** por lote, edición de campos + enlazar
**especie del catálogo** (rellena familia), borrado suave.
- **Catálogo de especies**: 14 hortícolas ibéricas (familia + nombres ES/EN),
sembrado idempotente al arrancar, búsqueda + autocompletado.
- **Germinación**: pruebas por lote (germinadas/muestra → tasa derivada), badge
reactivo. Avisos de viabilidad por especie (años de viabilidad + año de cosecha).
- **Schema v8**: procedencia, calendario de cultivo multi-mes (bitmask), escala de
abundancia, "necesita reproducción", chequeos de estado, formato de conservación.
- **Digitalización masiva**: import CSV aditivo, import/export JSON con
reconciliación LWW, borradores foto-first con OCR en dispositivo (es/en),
alta rápida "guardar y añadir otra".
- **Edición completa**: editar/borrar lotes (`updateLot`/`softDeleteLot`),
añadir/quitar nombres vernáculos (OR-Set con tombstones), editar campos,
fotos (portada, visor, borrado), enlaces externos.
- **Tests**: ~190 verdes, 0 saltados, incl. cubits de estado (`InventoryCubit`,
`VarietyDetailCubit`, `QuickAddCubit`). `analyze` + `format` limpios.
## Pendiente en el Bloque 1 (pulido) ⏳
- **QR de recuperación de la semilla raíz** + fichero de copia cifrado único y
restauración (ver [`backup-and-recovery.md`](backup-and-recovery.md)) — fase
planificada.
- **Comercio local sin red**: UI para `offer_status` (regalo/trueque/venta),
vista "lo que comparto", catálogo imprimible — fase planificada.
- **Cantidad precisa (gramos/nº) en la UI**: diferida a propósito. "Cuánto tengo"
lo responde la **escala de abundancia** (v8); la cantidad numérica se retomará
cuando las Offers reales la pidan (decisión 2026-07-09).
- (Opcional) almacenamiento cifrado de fotos fuera de la BD (hoy BLOB cifrado
dentro de la BD, que cumple la regla).
## Iconografía de los mockups (diseño futuro) 🎨
La app usa hoy **Material Icons genéricos**. Los iconos de los mockups **existen** ya
como font custom: **[`seedks.ttf`](../../seedks.ttf)** (raíz del repo, trackeado en
git), familia interna **"Seedks"**, **11 glifos** en `a``k` (U+0061U+006B), de la
misma época que [`../icons.svg`](../icons.svg) (2018). Preview renderizado:
[`../mockups/seedks-glyphs.png`](../mockups/seedks-glyphs.png).
Mapeo de glifos:
| Glifo | Icono | Glifo | Icono | Glifo | Icono |
|---|---|---|---|---|---|
| `a` | tarro | `e` | saco/bolsa | `i` | sobre |
| `b` | tarros (varios) | `f` | cucharilla | `j` | sobre vertiendo |
| `c` | búsqueda (lupa) | `g` | cuchara | `k` | semillas sueltas |
| `d` | mano compartiendo | `h` | taza | | |
**No** está cableado: falta declarar `fonts:` en
[`../../apps/app_seeds/pubspec.yaml`](../../apps/app_seeds/pubspec.yaml) y crear un
mapa codepoint→`IconData` (`fontFamily: 'Seedks'`). Recuperar la iconografía **no**
requiere SVGs nuevos. Iconos por familia/categoría y por unidad de cantidad =
trabajo de diseño para después del pulido del Bloque 1.
## Fuera de alcance (Bloque 2, no empezar) 🚫
Ofertas, mensajería, relays, Nostr, red de confianza, Ğ1, sincronización entre
dispositivos, backup completo. Ver [`../../CLAUDE.md`](../../CLAUDE.md).
## Cómo correr la app
**Requisitos previos** (una vez): los ficheros generados (Drift, slang) ya están
commiteados; si algo falla, regenera con:
```bash
cd apps/app_seeds
dart run build_runner build --delete-conflicting-outputs # Drift
dart run slang # i18n
```
**IntelliJ IDEA** (con plugins *Flutter* y *Dart* instalados):
1. Abre la carpeta raíz del repo (`tane`) como proyecto.
2. En *Settings → Languages & Frameworks → Flutter*, apunta al SDK de Flutter.
3. Hay una configuración de ejecución lista: **`app_seeds (tane)`** (en `.run/`),
cuyo *Dart entrypoint* es `apps/app_seeds/lib/main.dart`. Selecciónala en la
barra superior. Si no aparece, créala: *Run → Edit Configurations → + →
Flutter*, y pon *Dart entrypoint* = `apps/app_seeds/lib/main.dart`.
4. Elige un dispositivo (emulador Android, o *Linux desktop* / Chrome) en el
selector de dispositivos y pulsa ▶.
**Línea de comandos** (equivalente):
```bash
cd apps/app_seeds
flutter devices # ver dispositivos
flutter run -d linux # escritorio Linux (o -d chrome, o un emulador)
```
Nota: `flutter run` debe lanzarse desde `apps/app_seeds` (no desde la raíz del
workspace).