# Tanemaki — Decisiones abiertas y "qué chirría" *Revisión de conjunto antes de seguir construyendo. Reúne los cabos sueltos repartidos por los docs de diseño, ordenados por cuándo hay que decidirlos, y nombra las tensiones del plan que conviene mirar de frente.* > **Actualización (2026-07-10) — se abre la ronda social (Block 2).** El spike de de-risking ([spike-block2-findings.md](spike-block2-findings.md)) validó el happy-path completo de la capa social: derivación de la clave Nostr desde la semilla Ğ1, `OfferTransport`/NIP-99, mensajería NIP-17 (privada y con metadatos ocultos) y red de confianza estilo Duniter, todo sobre **una `NostrConnection` compartida con tres interfaces**. Con eso, la puerta de "no empezar Block 2" queda **levantada**. Orden de construcción dentro de Block 2: **(1) base de transporte en `commons_core`** (sobre librerías contrastadas — `nostr`, Dart puro, LGPL) → (2) UI de ofertas → (3) endurecer mensajería (entrega offline, vectores NIP-44, multidispositivo) → (4) parámetros WoT + arranque en frío. Los ítems de §B siguen siendo las decisiones a cerrar; §D.3 y §D.7 quedan **resueltos** por el spike. ## A) Decidir antes de escribir código de la Fase 1 (inventario) Estas fijan `schemaVersion = 1` y el arranque técnico: - **Formato de exportación/copia → ✅** un **archivo único cifrado**, abierto, documentado y versionado (volcado SQLite/CRDT + fotos + semilla envuelta). → [backup-and-recovery.md](backup-and-recovery.md) - **Cifrado en reposo (el "cómo" técnico):** SQLCipher + llave aleatoria en el almacén del sistema + QR de recuperación. Conceptualmente decidido; falta bajar el mecanismo. → [security-privacy.md](security-privacy.md) - **Identidad → ✅ una sola clave** raíz (Duniter/Ğ1), de la que se deriva la secp256k1 para Nostr. La clave simétrica que cifra la BD en reposo es un **detalle interno aparte** (no es una identidad), así que no contradice el "una sola identidad". → [g1-integration.md](g1-integration.md), [security-privacy.md](security-privacy.md) - **Detalles de modelo que fijan el esquema → ✅** `Quantity` como **tipo compartido** (Lot y Movement); `offer_status` **solo en Lot**; `category` **texto libre** prerrellenado desde `Species.family`. → [data-model.md](data-model.md) §6 - **Forma del lote (`LotType`) y envase (`Presentation`) → ✅** (schema v4). `LotType` pasa de `{seed, plant}` a **6 formas** append-only: `seed, seedling(plantón), plant, tree, bulb, cutting` — tras repasar el vocabulario de viveros/tiendas ("plantel" era mal nombre: es el semillero, no una unidad). El **envase** (`pot/tray/plug/bareRoot/rootBall`) es un **atributo opcional aparte**, no una cantidad, para no mezclar "cuántas" con "en qué formato". Germinación sigue siendo solo-`seed`. → [data-model.md](data-model.md) §2.3.2 - **Licencia** del código → ✅ **AGPL-3.0** (GPLv3 + cláusula de red; compatible con GPLv3 y con Duniter/Ğ1nkgo). Falta añadir el fichero `LICENSE` al abrir el repo. - **Varilla v1 → ✅ viable** con datos abiertos: nombres/identificación (Wikidata+GBIF, fácil), **conservación desde Kew SID** (dominio público, ~52k taxones), cuidados enlazados de Permapeople. Falta: confirmar acceso/descarga de Kew SID y el subconjunto curado a empaquetar. → [data-notes.md](data-notes.md) §3-ter - **Estructura del workspace** (`commons_core` + `app_seeds`, pub workspaces) — decidido; falta materializarlo. ## B) Decidir antes de la capa de compartir (Fase 3) — muy interdependientes - **Transporte de la capa social → Nostr (confirmado).** No se renuncia a Nostr: **Duniter no tiene mensajería**, así que Nostr es la vía para mensajes y ofertas. Se mantiene "una sola identidad" derivando la clave **secp256k1** (Nostr) de la semilla raíz Ğ1. Falta: confirmar madurez de los NIPs y la ruta de derivación. (Datapods de Duniter descartados: no están en servicio.) → [g1-integration.md](g1-integration.md) - **Estrategia de relays:** app-as-relay oportunista + proximidad física + relays comunitarios. → network-trust §3 - **Parámetros de la red de confianza:** umbral de certificaciones (¿5, estilo Duniter?), distancia, caducidad, certificación por colectivo. → network-trust §2 - **Mensajería:** alcance v1 (1:1 atada a oferta), apoyo en NIP-17. → network-trust §4 - **Reputación** atada a un trato/oferta cerrada (evitar reseñas falsas). → sharing-model §6 - **Precio:** ¿monedas comunitarias / de tiempo además de dinero? → sharing-model §6 - **Integración Ğ1 (moneda libre):** niveles 1–2 (precio en Ğ1 + enlace a cartera Ğecko/Cesium²/Ğ1nkgo) en la capa social; nivel 3 (reusar la WoT de Ğ1 como fuente de confianza) como estudio aparte. → [g1-integration.md](g1-integration.md) - **Ofertas de banco colectivo** (publica la entidad, no la persona). → sharing-model §6 - **Caducidad/revocación** de ofertas ya replicadas en relays. → sharing-model §6 - **Cambiar de identidad social — RESUELTO/IMPLEMENTADO (2026-07-10).** Se eligió una refinación de la vía (A) que **mantiene "backup UNA semilla"**: identidades seudónimas **derivadas de la misma semilla raíz con un índice de cuenta** (`NostrKeyDerivation.deriveFromSeed(seed, {account})`, HKDF one-way → no vinculables a Ğ1; **cuenta 0 = la identidad actual, byte-for-byte, sin rotar a nadie**). La cuenta activa se persiste en el keystore (`SocialAccountStore`), los stores por-identidad (chats/perfil/nombres) se **namespacian por cuenta** (cuenta 0 = claves legacy, sin migración), y `switchSocialAccount()` re-registra la porción social del DI y reinicia el inbox; la UI (perfil → "Tus identidades", crear/cambiar) aplica el cambio con un `RestartWidget` que reconstruye el árbol leyendo los singletons nuevos. La app NO toca la DB/inventario. Descartada la vía (B) reset total (perdía identidad+recuperación). → [[project-block2-spike]] ## C) Puede esperar (no bloquea nada ahora) - Negación plausible / bóveda señuelo; modo discreto. → security-privacy - Reconocimiento por foto en la varilla. - Respaldo social distribuido entre contactos. - Ampliar avisos legales más allá de Europa (empezar por jurisdicción común europea). → PLAN §6 - Segundo producto (biblioteca de cosas) y extracción de `Item/Holding` al core. → core-domain-boundary - Bloqueo de app: ¿activado por defecto o sugerido? → security-privacy - **Puente opcional con portales abiertos de biodiversidad (Darwin Core / GBIF / ALA).** Export *opt-in* de agrobiodiversidad (variedades cultivadas, taxonomía folk, nombres vernáculos) como Darwin Core Archive hacia un atlas ALA/GBIF — justo los datos que esos portales tienen más flojos. **No es fase ni código ahora:** solo se apunta como intención. Lo único que exige del diseño actual ya lo hacemos por otros motivos: anclar especies a GBIF key + Wikidata QID (data-model §2.2) y mantener el formato de exportación abierto/versionado (requisito de backup, Fase 1). **Guardas innegociables** para que no choque con el modelo de privacidad: opt-in por ítem, a nivel de banco colectivo (no persona), ubicación difuminada, solo material no sensible, y en un solo sentido (app → portal; nunca escribir de vuelta en un inventario privado). Argumento de interoperabilidad útil para NLnet/NGI. → data-notes §3-bis ## D) Qué chirría (tensiones a mirar de frente) 1. **La capa social es indivisible y grande.** "MVP = inventario + compartición local" subestima que "compartir" de verdad = **ofertas + mensajería + relays + red de confianza**, todo junto e interdependiente. Propuesta: replantear las fases como **(1) inventario** —entregable, sólido, en solitario— y **(2) el salto social** —un bloque grande, no un incremento—. Ser honestos con esto en el plan y en la financiación. 2. **Casi toda la dificultad vive en `commons_core`.** Identidad, sync CRDT, ofertas, pledge, red de confianza, **mensajería**, relays… `app_seeds` es, en comparación, ligero. En el fondo Tanemaki es **infraestructura de procomún** con las semillas como primera aplicación. Es buena noticia para NLnet/NGI Zero (financian infraestructura), pero hay que asumir que lo "sencillo" (semillas) es la punta del iceberg y comunicar el proyecto en consecuencia. 3. **Apuesta fuerte por Nostr.** Ofertas, mensajes y confianza dependerían de NIPs en evolución (99 / 17 / 85). La abstracción `OfferTransport` amortigua las ofertas, pero mensajería y confianza también se apoyan en Nostr → más acoplamiento del que sugería el plan. Revisar si un solo protocolo lo cubre bien o si conviene aislar también mensajería y confianza tras interfaces. 4. **Cifrado en reposo + sync CRDT + multidispositivo.** Hay que asegurar que la sincronización **no filtra la llave ni datos en claro**, y que la llave (QR) llega bien al segundo dispositivo. Encaja, pero es un punto técnico fino que conviene prototipar pronto. 5. **La "varilla" y los datos de conservación** necesitan una fuente y una curación que **aún no tenemos**. Puede ser más trabajo del que parece (y es, a la vez, de lo que más valor humano aporta). 6. **Alcance vs. sostenibilidad de un mantenedor.** El conjunto (inventario + cripto + P2P + confianza + mensajería + relays, en varias plataformas) es **mucho** para "proyecto personal + IA". Refuerza la necesidad de: fases honestas, comunidad temprana, y financiación (NLnet) para la parte social. La Fase 1 sí es abordable en solitario. 7. **Identidad — RESUELTO: una sola identidad, dos claves derivadas.** Una **semilla raíz** estilo Duniter/Ğ1 (perfil, certificaciones, Ğ1) de la que se **deriva** determinísticamente la clave **secp256k1** para Nostr (mensajes, ofertas). Para la persona es *una sola identidad y una sola copia* (el QR de la semilla). **Nostr no se descarta** — es imprescindible porque **Duniter carece de mensajería**. No hay contradicción con "una sola clave": son subclaves de una raíz. → [g1-integration.md](g1-integration.md) ## Recomendación de orden Cerrar el bloque **(A)** — son pocas decisiones y desbloquean construir el inventario, que es valioso por sí solo y de bajo riesgo. Dejar **(B)** para una ronda de diseño específica de la capa social (con su propia financiación si llega). Y asumir explícitamente el punto **(D.1)**: replantear las fases para que "lo social" sea un hito grande y no una coletilla del MVP.