NIPs in progress
TresPies is a bilingual equity-data and civic firm building on the Nostr stack — a census atlas on MKStack, Spanish layers for Soapbox-family apps, an archive relay. These are the protocol gaps we keep hitting while we build, published before they're polished.
The status labels are honest: most of these are research, not drafts. Nothing here is a ratified NIP, or even a submitted one. We publish anyway because the venue works that way — NostrHub calls itself "a meritocracy you configure yourself," and the way into a meritocracy is work, in public, with receipts.
Every idea links its evidence. When one matures, we'll propose it where proposals belong — as a long-form draft on NostrHub — and this page will say so. Tell us where we're wrong: cruz@trespiesdesign.com.
NIPs en progreso
TresPies es una firma bilingüe de datos de equidad y trabajo cívico que construye sobre el stack de Nostr — un atlas del censo sobre MKStack, capas en español para las aplicaciones de la familia Soapbox, un relay de archivo. Estas son las brechas del protocolo con las que seguimos tropezando mientras construimos, publicadas antes de estar pulidas.
Las etiquetas de estado son honestas: la mayoría de esto es investigación, no borradores. Nada aquí es un NIP ratificado, ni siquiera uno presentado. Publicamos de todos modos porque así funciona este espacio — NostrHub se describe como "una meritocracia que tú mismo configuras", y a una meritocracia se entra con trabajo, en público, con evidencia.
Cada idea enlaza sus fuentes. Cuando alguna madure, la propondremos donde corresponde — como borrador de formato largo en NostrHub — y esta página lo dirá. Dinos en qué nos equivocamos: cruz@trespiesdesign.com.
- Language labels clients actually useDrafting
- Push delivery, revivedResearching
- Stop wiping profiles: merge semantics for replaceable eventsResearching
- Relays that say what they keepExploring
- Public datasets on open railsExploring
Language labels clients actually use
Etiquetas de idioma que los clientes de verdad usen
Nostr has no ratified way to say what language an event is written in. Soapbox's own founder tried — NIP-37 "Language Tag" closed unmerged in 2024, with the standing objection that "all automatic translation tools will already detect the language automatically anyway." A second proposal (PR #1127) is still open, still unmerged. Meanwhile the read side already shipped: NIP-50 defines a language: search filter and relay software implements it — but almost nothing on the publish side labels consistently, so there is nothing reliable to filter. Result: a Spanish-speaking user cannot dependably ask for their own language.
The gap
This is not a missing spec. NIP-32 labeling is ratified and its spec literally contains the example — ["L","ISO-639-1"], ["l","en","ISO-639-1"]. What's missing is a publish-side convention plus an adoption loop. And the auto-detection objection fails exactly where we live: short notes, code-mixed Spanish/English, and relay-level filtering that shouldn't require content analysis of every event.
What we're sketching
A thin convention document: NIP-32 language labels on kinds 1 and 30023, localized NIP-89 handler metadata so app directories aren't English-only, and a namespace caution (NIP-C0 already uses an l tag for programming language). Reference implementations, not just prose: an MKStack skill, and our es-layer forks labeling on publish. Where PR #1127 overlaps, we support it rather than compete with it.
Why us
Bilingual isn't a feature for us; it's the firm's thesis. We ship Spanish layers with symmetric EN/ES parity gates, and we hit this gap on every one of them.
Receipts
- NIP-37 "Language Tag" — PR #632 — closed unmerged 2024-06-07, objection quoted from the thread
- PR #1127 — Internationalization and Localization — still open, unmerged
- NIP-32: Labeling — ratified; contains the ISO-639-1 language example
- NIP-50: Search Capability —
language:filter, read-side - NIP-C0: Code Snippets — the other
ltag; namespace caution - ditto-relay — shipping
language:search filtering today
Nostr no tiene una forma ratificada de decir en qué idioma está escrito un evento. El propio fundador de Soapbox lo intentó — NIP-37 "Language Tag" se cerró sin fusionarse en 2024, con la objeción de que "las herramientas de traducción automática ya detectan el idioma de todos modos". Una segunda propuesta (PR #1127) sigue abierta, sin fusionarse. Mientras tanto, el lado de lectura ya existe: NIP-50 define un filtro de búsqueda language: y hay software de relay que lo implementa — pero casi nadie etiqueta al publicar de forma consistente, así que no hay nada confiable que filtrar. Resultado: una persona hispanohablante no puede pedir su propio idioma de manera confiable.
La brecha
No falta una especificación. NIP-32 (etiquetado) está ratificado y su propio texto contiene el ejemplo — ["L","ISO-639-1"], ["l","en","ISO-639-1"]. Lo que falta es una convención del lado de publicación y un ciclo de adopción. Y la objeción de la detección automática falla justo donde vivimos nosotros: notas cortas, texto mezclado español/inglés, y filtrado a nivel de relay que no debería exigir analizar el contenido de cada evento.
Lo que estamos esbozando
Un documento de convención delgado: etiquetas de idioma NIP-32 en los kinds 1 y 30023, metadatos NIP-89 localizados para que los directorios de aplicaciones no existan solo en inglés, y una advertencia de espacios de nombres (NIP-C0 ya usa una etiqueta l para lenguaje de programación). Implementaciones de referencia, no solo prosa: un skill de MKStack, y nuestras capas en español etiquetando al publicar. Donde PR #1127 coincida, lo apoyamos en lugar de competir.
Por qué nosotros
Para nosotros lo bilingüe no es una función; es la tesis de la firma. Publicamos capas en español con verificaciones simétricas de paridad EN/ES, y chocamos con esta brecha en cada una.
Evidencia
- NIP-37 "Language Tag" — PR #632 — cerrado sin fusionar el 2024-06-07; la objeción está citada del hilo
- PR #1127 — Internationalization and Localization — sigue abierto, sin fusionar
- NIP-32: Labeling — ratificado; contiene el ejemplo ISO-639-1
- NIP-50: Search Capability — filtro
language:, lado de lectura - NIP-C0: Code Snippets — la otra etiqueta
l; advertencia de espacios de nombres - ditto-relay — ya implementa búsqueda con
language:
Push delivery, revived
Notificaciones push, retomadas
No NIP covers push notifications. We scanned the full NIP index — nothing numbered, lettered, or hex-coded addresses how an event reaches a phone that isn't looking. The one serious attempt, Amethyst's "Event Watcher API" (PR #1528), had already run in production for about a year before it was even proposed — and it still closed unmerged in 2025, with the author's own note that Pokey's success made him question whether the idea was worth pursuing. The gap didn't close; the person carrying it put it down.
Why it matters more than it looks
Apple's Lockdown Mode blocks Service Workers entirely, so PWA web-push isn't degraded there — it's absent. The users who opt into the highest security get the least notification capability, and every consumer Nostr app re-solves this privately or ships without it.
What we're sketching
Study before proposing: PR #1528's design and Pokey's working model first. The likely shape is a slim registration spec with wrapped delivery — the push server should never learn which pubkey you watch. But the first deliverable is practical, not protocol: an MKStack skill that standardizes the non-protocol fallback (native push via Capacitor/APNs/FCM, web-push where it exists, honest Lockdown Mode behavior) so scaffolded apps stop re-solving it one at a time. A fallback pattern people actually ship beats a spec nobody implements.
Why us
We're building bilingual consumer surfaces on this stack, and civic information is time-sensitive — a deadline notice that arrives late is a notice that didn't arrive.
Receipts
- PR #1528 — Push Notification, Event Watcher API — closed unmerged 2025-07-31; in production on Amethyst ~a year prior
- NIP index — scanned in full; no push standard exists
- MKStack
lockdown-modeskill — Service Workers sit in the blocked-entirely tier - MKStack
capacitorskill — the native wrap the fallback rides on
Ningún NIP cubre las notificaciones push. Revisamos el índice completo de NIPs — nada, con número, letra o código hex, define cómo un evento llega a un teléfono que no está mirando. El único intento serio, el "Event Watcher API" de Amethyst (PR #1528), ya llevaba cerca de un año funcionando en producción antes de proponerse — y aun así se cerró sin fusionarse en 2025, con una nota del propio autor diciendo que el éxito de Pokey lo hizo dudar de si valía la pena seguir. La brecha no se cerró; la persona que la cargaba la soltó.
Por qué importa más de lo que parece
El Lockdown Mode de Apple bloquea los Service Workers por completo, así que el push web de una PWA ahí no se degrada — desaparece. Las personas que eligen la máxima seguridad reciben la menor capacidad de notificación, y cada aplicación de consumo en Nostr resuelve esto en privado o publica sin resolverlo.
Lo que estamos esbozando
Estudiar antes de proponer: primero el diseño de PR #1528 y el modelo de Pokey. La forma probable es una especificación delgada de registro con entrega envuelta — el servidor de push nunca debería saber qué pubkey observas. Pero el primer entregable es práctico, no de protocolo: un skill de MKStack que estandarice la alternativa fuera del protocolo (push nativo vía Capacitor/APNs/FCM, push web donde exista, comportamiento honesto bajo Lockdown Mode) para que las aplicaciones dejen de resolverlo una por una. Un patrón que la gente de verdad publica vale más que una especificación que nadie implementa.
Por qué nosotros
Construimos superficies de consumo bilingües sobre este stack, y la información cívica es sensible al tiempo — un aviso de plazo que llega tarde es un aviso que no llegó.
Evidencia
- PR #1528 — Push Notification, Event Watcher API — cerrado sin fusionar el 2025-07-31; en producción en Amethyst ~un año antes
- Índice de NIPs — revisado completo; no existe estándar de push
- Skill
lockdown-modede MKStack — los Service Workers están en el nivel bloqueado-por-completo - Skill
capacitorde MKStack — el envoltorio nativo sobre el que corre la alternativa
Stop wiping profiles: merge semantics for replaceable events
Dejar de borrar perfiles: semántica de fusión para eventos reemplazables
Profiles (kind 0) and contact lists (kind 3) are replaceable events: last write wins, whole event. A client that publishes its own partial view of a profile silently erases every field it doesn't understand — for everyone, everywhere. The protocol's own tracker has documented this since 2023 (issue #261), and it bites real users: Damus's "Balaji's bug" was a profile wiped by exactly this mechanism. Relays can't fix it — for each pubkey and kind, only the latest event is stored. Only clients can.
The gap
There is no stated rule that a client publishing a replaceable event should first merge against the latest known state and preserve fields it doesn't recognize. Every client that gets this right does so by folklore; every new client gets a chance to wipe your lightning address.
What we're sketching
A small SHOULD: before publishing a replaceable kind, fetch the latest known event, deep-merge your changes into it, and preserve unknown fields verbatim. Alongside the prose, the part we think matters more: a conformance fixture set — event pairs where a correct merge has one right answer — and a reference implementation as an MKStack skill/hook, so scaffolded apps get safe publishing without reading a spec. Open question we're researching: whether unknown-field preservation can be specified tightly enough to test without freezing legitimate field deletion.
Why us
We're shipping apps on the scaffold this failure class lives in, and "your app quietly destroyed my profile" is the kind of trust failure a civic tool can't survive.
Receipts
- nostr-protocol/nips issue #261 — the field-overwrite failure class, documented and open
- Damus issue #1994 — "Profile is wiped (Balaji's bug)"
- Damus issue #2264 — bookmarks wiped — same lesson, different surface
Los perfiles (kind 0) y las listas de contactos (kind 3) son eventos reemplazables: gana la última escritura, el evento completo. Un cliente que publica su vista parcial de un perfil borra en silencio cada campo que no entiende — para todos, en todas partes. El propio rastreador del protocolo lo documenta desde 2023 (issue #261), y afecta a usuarios reales: el "bug de Balaji" en Damus fue un perfil borrado exactamente por este mecanismo. Los relays no pueden arreglarlo — por cada pubkey y kind solo se guarda el evento más reciente. Solo los clientes pueden.
La brecha
No existe una regla que diga que un cliente, antes de publicar un evento reemplazable, debería fusionar contra el último estado conocido y preservar los campos que no reconoce. Cada cliente que lo hace bien lo hace por tradición oral; cada cliente nuevo tiene su oportunidad de borrar tu dirección de lightning.
Lo que estamos esbozando
Un SHOULD pequeño: antes de publicar un kind reemplazable, obtener el último evento conocido, fusionar los cambios sobre él, y preservar los campos desconocidos tal cual. Junto a la prosa, la parte que creemos que importa más: un conjunto de casos de conformidad — pares de eventos donde una fusión correcta tiene una sola respuesta válida — y una implementación de referencia como skill/hook de MKStack, para que las aplicaciones generadas publiquen de forma segura sin leer una especificación. Pregunta abierta que investigamos: si la preservación de campos desconocidos puede especificarse con suficiente precisión para probarse sin congelar el borrado legítimo de campos.
Por qué nosotros
Publicamos aplicaciones sobre el mismo andamiaje donde vive esta clase de falla, y "tu aplicación destruyó mi perfil en silencio" es el tipo de falla de confianza que una herramienta cívica no sobrevive.
Evidencia
- nostr-protocol/nips issue #261 — la clase de falla de sobreescritura de campos, documentada y abierta
- Damus issue #1994 — "Profile is wiped (Balaji's bug)"
- Damus issue #2264 — marcadores borrados — misma lección, otra superficie
Relays that say what they keep
Relays que digan qué guardan
Not one relay or media host we could find publishes a contractual durability promise — free or paid. The measured economics explain why: 95% of free relays can't cover operating costs from zap income, and 64% receive zero zaps at all (Wei & Tyson, CoNEXT '25). Users treat relays as storage; the economics say they're caches. NIP-11 lets a relay describe its operational limits, and NIP-66 monitors whether a relay is alive — but there is no standard, machine-readable way for a relay to declare how long it keeps events, and nothing that checks such a declaration against observed behavior.
The gap
Durability on Nostr is currently a vibe. A user picking write relays, or an organization with records-retention obligations, has no signal to select on — liveness isn't retention, and payment isn't a promise.
What we're sketching
Three pieces that only work together: a machine-readable retention declaration (a NIP-11 extension or companion event), NIP-66-class monitors that verify claims longitudinally — "promised 30 days; observed 90" — so declarations earn reputations, and client UX that surfaces it at relay-selection time. Declared retention that nobody verifies is marketing; verified retention is infrastructure.
Why us
We run the archive-relay pattern ourselves (own strfry as source of truth, public relays as reach), and we build for civic organizations that answer to actual records-retention rules.
Receipts
- Wei & Tyson — An Empirical Analysis of the Nostr Social Network — 95% / 64% / p90 zap-income figures
- NIP-11: Relay Information Document —
limitationfields exist; no retention promise does - NIP-66: Relay Discovery and Liveness Monitoring — liveness, not durability
Ningún relay ni servidor de medios que pudimos encontrar publica una promesa contractual de durabilidad — gratuito o de pago. La economía medida explica por qué: el 95% de los relays gratuitos no cubre sus costos operativos con ingresos por zaps, y el 64% no recibe ningún zap (Wei & Tyson, CoNEXT '25). La gente trata los relays como almacenamiento; la economía dice que son cachés. NIP-11 permite que un relay describa sus límites operativos, y NIP-66 monitorea si un relay está vivo — pero no existe una forma estándar y legible por máquina de que un relay declare cuánto tiempo guarda los eventos, ni nada que compare esa declaración con el comportamiento observado.
La brecha
Hoy la durabilidad en Nostr es una sensación. Una persona eligiendo sus relays de escritura, o una organización con obligaciones de retención de registros, no tiene ninguna señal sobre la cual decidir — estar vivo no es retener, y cobrar no es prometer.
Lo que estamos esbozando
Tres piezas que solo funcionan juntas: una declaración de retención legible por máquina (una extensión de NIP-11 o un evento compañero), monitores tipo NIP-66 que verifiquen las declaraciones a lo largo del tiempo — "prometió 30 días; se observaron 90" — para que las declaraciones ganen reputación, y una interfaz de cliente que lo muestre al momento de elegir relays. Una retención declarada que nadie verifica es publicidad; una retención verificada es infraestructura.
Por qué nosotros
Nosotros mismos operamos el patrón de relay de archivo (strfry propio como fuente de verdad, relays públicos como alcance), y construimos para organizaciones cívicas que responden a reglas reales de retención de registros.
Evidencia
- Wei & Tyson — An Empirical Analysis of the Nostr Social Network — las cifras de 95% / 64% / p90 de ingresos por zaps
- NIP-11: Relay Information Document — existen campos de
limitation; una promesa de retención, no - NIP-66: Relay Discovery and Liveness Monitoring — vivacidad, no durabilidad
Public datasets on open rails
Datos públicos sobre rieles abiertos
Public-interest data — census extracts, language-access data, eviction filings — lives on servers that get defunded, redesigned, or quietly taken down. Nostr already over-replicates social events (the average post lands on 34.6 relays, measured), but it has no convention for announcing a dataset: what it is, where it came from, which vintage, what license, where the mirrors are. Before building a census atlas on this stack we looked for a precedent; none exists.
The gap
NIP-94 describes a file. A dataset needs more: source authority, vintage (ACS 2019–2023 is not ACS 2020–2024), geographic coverage, license, content hash, and a mirror list a client can actually resolve. Without that, "the data is decentralized" is a slogan — you can't verify what a dashboard is built on, and you can't re-host what you can't identify.
What we're sketching
A NIP-94-family announcement for datasets: source, vintage, geography, license, sha256, mirror list (Blossom BUD-04 mirroring makes the copies real). The consumer story: a civic dashboard cites the announcement event, anyone verifies the hash, anyone re-hosts the blob, and the dashboard survives its original host. We're dogfooding the substrate now — a bilingual census atlas served entirely from static tiles — and the announcement convention is the missing provenance layer under it.
Why us
Equity data for overlooked communities is our practice. The communities most likely to need this data are the least served by the infrastructure that currently holds it.
Receipts
- NIP-94: File Metadata — the base shape to extend
- BUD-04: Mirroring Blobs — server-to-server mirroring; makes mirror lists real
- Wei & Tyson — replication exists (34.6 relays/event); provenance doesn't
- The Soapbox Stack Operator Manual, ch. 09 — the atlas substrate we're dogfooding
Los datos de interés público — extractos del censo, datos de acceso lingüístico, registros de desalojos — viven en servidores que pierden fondos, se rediseñan o se retiran sin aviso. Nostr ya sobre-replica los eventos sociales (una publicación promedio llega a 34.6 relays, medido), pero no tiene una convención para anunciar un conjunto de datos: qué es, de dónde viene, de qué vendimia, con qué licencia, dónde están los espejos. Antes de construir un atlas del censo sobre este stack buscamos un precedente; no existe.
La brecha
NIP-94 describe un archivo. Un conjunto de datos necesita más: autoridad de origen, vendimia (ACS 2019–2023 no es ACS 2020–2024), cobertura geográfica, licencia, hash del contenido, y una lista de espejos que un cliente pueda resolver. Sin eso, "los datos son descentralizados" es un eslogan — no puedes verificar sobre qué está construido un tablero, y no puedes re-hospedar lo que no puedes identificar.
Lo que estamos esbozando
Un anuncio de la familia NIP-94 para conjuntos de datos: origen, vendimia, geografía, licencia, sha256, lista de espejos (el espejado BUD-04 de Blossom hace que las copias sean reales). La historia del consumidor: un tablero cívico cita el evento de anuncio, cualquiera verifica el hash, cualquiera re-hospeda el blob, y el tablero sobrevive a su servidor original. Ya estamos probando el sustrato — un atlas del censo bilingüe servido enteramente desde teselas estáticas — y la convención de anuncio es la capa de procedencia que le falta debajo.
Por qué nosotros
Los datos de equidad para comunidades pasadas por alto son nuestra práctica. Las comunidades que más van a necesitar estos datos son las peor servidas por la infraestructura que hoy los guarda.
Evidencia
- NIP-94: File Metadata — la forma base a extender
- BUD-04: Mirroring Blobs — espejado servidor a servidor; hace reales las listas de espejos
- Wei & Tyson — la replicación existe (34.6 relays/evento); la procedencia no
- Manual del operador del stack Soapbox, cap. 09 — el sustrato del atlas que estamos probando
Watching, not carrying
Gaps we track without presuming to lead them. Listed so you know we know.
- NIP-41 key migration (PR #829) — open since October 2023, stalled on the griefing debate. Key custody is upstream of everything on this page; we watch it and design around its absence.
- NIP-62: Request to Vanish × the EDPB's blockchain guidance (finalized 2026-07-08) — MUST-level deletion meets "technically hard to delete is not an exemption." An operator-focused explainer is in progress.
- NIP-77: Negentropy syncing — draft/optional; adoption determines how cheap archive-relay sync gets.
- NIP-55: Android signer application — the third signing standard consumer apps must support alongside NIP-07 and NIP-46.
Observando, sin cargar
Brechas que seguimos sin pretender liderarlas. Las listamos para que sepas que las conocemos.
- Migración de claves NIP-41 (PR #829) — abierto desde octubre de 2023, estancado en el debate sobre abuso ("griefing"). La custodia de claves está aguas arriba de todo lo que hay en esta página; la observamos y diseñamos alrededor de su ausencia.
- NIP-62: Request to Vanish × la guía de blockchain del EDPB (finalizada el 2026-07-08) — el borrado de nivel MUST se encuentra con "que sea técnicamente difícil de borrar no es una exención". Hay un explicador para operadores en camino.
- NIP-77: Sincronización negentropy — borrador/opcional; su adopción determina qué tan barata resulta la sincronización de un relay de archivo.
- NIP-55: Aplicación firmante en Android — el tercer estándar de firma que las aplicaciones de consumo deben soportar junto a NIP-07 y NIP-46.
Contact and provenance
Write to cruz@trespiesdesign.com. An npub with NIP-05 verification on this domain ships with our first git-anchored repo — we're setting up key custody deliberately, not quickly, for the reasons this page keeps citing.
Everything above is grounded in the Soapbox Stack Operator Manual we maintain on this same domain — 16 chapters, live-verified citations, raw markdown and an llms.txt for agents. The raw markdown for this page is indexed at /NIPs/llms.txt, same convention.
Contacto y procedencia
Escríbenos a cruz@trespiesdesign.com. Un npub con verificación NIP-05 en este dominio llegará con nuestro primer repositorio anclado en git — estamos configurando la custodia de claves con calma deliberada, no con prisa, por las mismas razones que esta página cita una y otra vez.
Todo lo anterior está fundamentado en el Manual del operador del stack Soapbox que mantenemos en este mismo dominio — 16 capítulos, citas verificadas en vivo, markdown crudo y un llms.txt para agentes. El markdown crudo de esta página está indexado en /NIPs/llms.txt, misma convención.