tane/docs/design/sharing-model.md
vjrj adf396d49d feat(plantare): surface product link + dates; spec the bilateral record
The Plantaré screen stored madeOn/dueBy/varietyId but showed none of them,
so it felt half-built. Surface what's already there (no schema change):

- watchPlantareViews() joins each commitment with its variety label
- tile shows the made-on date, a "Return by {date}" line (amber + "overdue"
  when an open promise is past due, via new seedWarning colour), the variety
  name, and taps through to /variety/:id
- add sheet gains an optional return-by date picker (createPlantare already
  took dueBy)
- variety detail shows a read-only commitments section (hidden when empty,
  no add button — honours the single hand-over door)
- i18n en/es/pt/ast; tests for the join, dueBy round-trip, tile, and section

Also specs the deferred two-sided record in docs/design/plantare-bilateral.md
(Nostr pubkey counterparty, PlantareTransport propose->accept->counter-sign,
deferred key/signature/movement columns, provenance DAG, reputation anchor),
with a faithful transcription of the paper Plantaré v0.4 (BAH-Semillero 2009,
CC-BY-SA). Cross-linked from data-model §2.7 and sharing-model §6.
2026-07-13 18:06:33 +02:00

109 lines
8.5 KiB
Markdown
Raw 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.

# Tane — Modelo de compartición y mercado (nota de diseño)
*Documento de reflexión. Lengua: español (discusión). Desarrolla la Capa 3 del [PLAN.md](../../PLAN.md) §3§4 y §6, y conecta con el modelo de datos ([data-model.md](data-model.md)).*
Dos cosas a resolver aquí: **(a)** cómo se *anuncia* lo que alguien comparte, de forma descentralizada, más allá del pagaré bilateral (que es el cierre, no el escaparate); y **(b)** permitir que quien quiera pueda **pedir dinero** —mercado— sin traicionar el alma del proyecto ni aumentar el riesgo legal de la gente.
---
## 1. El Plantare no es el anuncio
Aclaración conceptual, porque es fácil mezclarlos:
- El **Plantare** (§5-bis) es el *cierre bilateral* de un intercambio: el compromiso firmado entre dos personas cuando ya se han encontrado. Es privado, entre las dos partes.
- Lo que falta es el **escaparate**: cómo anuncia alguien "tengo esto para dar/cambiar/vender" para que otra persona *lo descubra* antes de que exista trato alguno. Eso es la **Oferta (Offer)**.
Oferta → contacto → trato → (opcional) Plantare. El pagaré es el último paso, no el primero.
---
## 2. La Oferta (Offer): anunciar sin exponerse
Una **Offer** es una declaración *firmada y publicada* a la red: "yo (clave pública) ofrezco [resumen de variedad] cerca de [ubicación aproximada], como [regalo/trueque/venta], [condiciones]". Principios:
- **Revela solo lo que elijas.** La Offer es un objeto distinto del `Lot`/inventario: publicas un resumen (nombre, foto, condiciones), **nunca tu inventario completo ni tu dirección exacta**. La separación Offer↔Lot es una decisión de privacidad, no solo técnica.
- **Ubicación aproximada siempre.** Geohash de baja precisión (el "10 km near you" de los mockups), nunca coordenadas exactas. La precisión la sube la persona solo al cerrar trato, en privado.
- **Identidad = clave pública** que controlas (Nostr). Sin registro central, sin email obligatorio.
- **La app presenta; la gente cierra.** La Offer enlaza a un canal de contacto (mensaje cifrado). El trato se cierra entre personas. Es el "efecto Wallapop" sin el intermediario Wallapop.
- **Estacionalidad y caducidad.** Las semillas son de temporada: la Offer tiene estado (`active`/`reserved`/`closed`) y caducidad (`expires_at`); hay que refrescarla. Una oferta vieja no debe engañar.
- **Descubrimiento** = consulta a relays/instancias por geohash + categoría → es la pantalla de búsqueda de los mockups (`04_search_page`, `05_search_item`).
### Transporte concreto: NIP-99
Detrás de la abstracción `OfferTransport` (PLAN §4), el primer backend es **Nostr NIP-99 ("Classified Listings")**: evento `kind:30402` (activo) / `30403` (borrador), con campos estructurados de **título, resumen, precio (importe + moneda), ubicación y estado**. Es decir: **el estándar ya contempla precio y moneda de serie**, así que regalo, trueque y venta caben en el mismo mecanismo. Existe ecosistema real (p.ej. Shopstr) del que aprender. La ubicación puede acompañarse de un tag geohash. ActivityPub / FEP-0837 queda como segundo backend posible.
---
## 3. Los cuatro modos de una Offer
`offer_type`:
- **Regalo (gift)** — gratis, sin retorno esperado. El don puro.
- **Trueque (exchange)** — a cambio de otras semillas, trabajo, o el compromiso Plantare (devolver después). Es el modo de reciprocidad.
- **Venta (sale)** — dinero. Precio + moneda. *(la novedad que pides)*
- **Busco (wanted)** — el inverso: anunciar *demanda*, no oferta ("busco semilla de tomate rosa de Barbastro"). Barato de añadir y muy útil en bancos y ferias.
---
## 4. El mercado (dinero): cómo hacerlo sin traicionar el proyecto
Permitir vender es legítimo y realista —hay quien produce semilla artesanal, quien vende excedente— pero toca el alma anti-monopolio del proyecto y la ley. Cómo cuadrarlo, con las tensiones **nombradas**, no escondidas:
### 4.1 Valores: el don es de primera clase; la venta, permitida, no promovida
- En la interfaz, **regalo y trueque se muestran primero**; la venta es un modo que *eliges*, nunca el defecto. Preservas el ethos sin imponer tu criterio a nadie (autonomía de la persona).
- Sin gamificación de la venta, sin "destacados de pago", sin ránkings de vendedores. Vender es una etiqueta más, no el eje.
### 4.2 Legal: vender reengancha justo el problema Kokopelli
Esto es lo delicado. La **venta** de variedades tradicionales no registradas es exactamente lo que multó a Kokopelli; el regalo/trueque entre aficionados o agricultores está mucho más protegido (PLAN §6). Al añadir "venta" aumentas la exposición legal *de tus usuarios*. Mitigaciones de diseño:
- **Tane no es un mercado, es infraestructura neutral.** La app no opera el mercado, no publica un catálogo central, no pone en venta nada: son las personas, entre iguales (como flohmarkt). Esta neutralidad es la mejor defensa (replica por qué Kokopelli fue vulnerable —venta + operador central identificable— y evita ambas).
- **Aviso contextual por región, no policía.** Al marcar una Offer como "venta", la app puede mostrar una nota suave y dependiente del país ("vender semilla de variedades no registradas puede estar restringido en tu país"). Informar, no bloquear, no vigilar.
- **La venta prioriza el marco de conservación/compartición** en el discurso y el diseño; el dinero es una opción, no la portada.
### 4.3 Nada de rieles de pago (esto es innegociable)
- **La app NO procesa pagos, NO cobra comisión, NO retiene dinero, NO muestra publicidad.** El pago se acuerda **directamente entre las personas** (efectivo, su propia transferencia, lo que sea), *fuera* de la app.
- Meter pagos dentro convertiría a Tane en operador central: obligaciones KYC/AML, custodia de fondos, y reintroduce justo la centralización que se quiere evitar. Además mataría la sostenibilidad (§7: financiación por subvenciones/donaciones, no por comisiones).
- Resultado: es el "efecto Wallapop sin Wallapop" también para la venta — anuncia y conecta; el dinero cambia de manos entre personas.
### 4.4 Representación del precio
`price_amount` (decimal) + `price_currency` (ISO 4217, admitiendo también monedas locales/comunitarias) + `price_negotiable` (bool). Para trueque, `exchange_terms` (texto: "a cambio de semilla de legumbre" / "o X horas"). El precio puede ser "a convenir".
### 4.5 Confianza y abuso
- Un mercado abierto y descentralizado atrae **spam y estafas**. La red de confianza (Capa 4) es el filtro: mostrar primero ofertas de gente dentro de tu grafo de confianza; el ámbito local/geohash ya acota mucho.
- Tras un trato, valoraciones/comentarios (los del mockup de perfil `09_public_profile`) — descentralizados, sin bloquear a nadie.
---
## 5. Añadidos al modelo de datos
Nueva entidad publicable (se serializa a NIP-99 / ActivityPub). En inglés, para [data-model.md](data-model.md):
**`Offer`**
| Columna | Tipo | Notas |
|---|---|---|
| `id` | UUID | |
| `lot_id` | UUID → `Lot` | Nullable (puedes ofrecer sin exponer un lote concreto; `wanted` no lo usa). |
| `variety_summary` | TEXT/JSON | Desnormalizado: nombre + ref de foto que *eliges* publicar (privacidad). |
| `offer_type` | enum | `gift` / `exchange` / `sale` / `wanted`. |
| `price_amount` | DECIMAL | Nullable (solo `sale`). |
| `price_currency` | TEXT | Nullable. ISO 4217 o moneda local. |
| `price_negotiable` | BOOLEAN | |
| `exchange_terms` | TEXT | Nullable (para `exchange`). |
| `approx_geohash` | TEXT | Baja precisión. |
| `radius_km` | INTEGER | Ámbito. |
| `status` | enum | `active` / `reserved` / `closed`. |
| `published_at` / `expires_at` | | Estacionalidad. |
| `transport_ref` | TEXT | id del evento en el relay (NIP-99) / objeto AP. |
| `author_key` | TEXT | Clave pública que publica. |
| *(+ columnas comunes)* | | |
`Offer` es distinta de `Lot` **a propósito**: publicar revela solo lo elegido. Un trato cerrado puede generar un `Movement` (`given`) y, si es trueque con retorno, un `Plantare`.
---
## 6. A decidir
- ¿Las valoraciones (reputación) se atan a un `Movement`/`Offer` cerrado para evitar reseñas falsas? (Probablemente sí, Capa 4.) El ancla fuerte es el Plantaré bilateral firmado — spec en [plantare-bilateral.md](plantare-bilateral.md).
- ¿Permitir monedas comunitarias/tiempo explícitamente en `price_currency` (guiño al espíritu Plantare como "moneda de semillas")? Interesante.
- ¿Ofertas de banco colectivo (publica el banco, no la persona)? Afecta a identidad/permisos (Capa 23).
- ¿Cómo se revoca/expira una Offer publicada en relays que ya la replicaron? (Estado `closed` + caducidad; los relays acaban soltando lo viejo.)