Lo Que No Lance

Me salte el martes pasado. Hoy tambien es martes, y hoy tampoco hay app nueva.

Este es el post donde lo digo en voz alta en vez de saltarme dos semanas en silencio y esperar que nadie estuviera contando. Dos semanas, cero lanzamientos. La ultima vez que paso fue en febrero, cuando App Review se sento sobre dos envios y escribi sobre la espera en lugar de lanzar. La diferencia es que febrero fue culpa de Apple y esta es mia.

Lo que si paso es que lance un monton de actualizaciones, pase una cantidad poco razonable de horas montando infraestructura de servidor para un bloqueador de anuncios, y termine genuinamente cansado. Las tres cosas merecen una explicacion.

Lo que si salio

Soundshine 1.3.3: la razon real de que esta tomara una semana fue un bug de corrupcion que solo aparecia cuando dos cosas leian el anillo de audio a la vez. Lo tenia direccionando el anillo con cursores por cliente, que se desalinean en el momento en que los lectores no coinciden sobre donde estan. Ahora direcciona por tiempo de muestra, que no se puede desalinear porque la linea de tiempo es la misma para todos. El controlador tambien reporta una clase concreta de control de silencio, asi que el dispositivo por fin tiene un mute que el sistema respeta, y anuncia los cambios de volumen y silencio en vez de hacerlos calladamente. El panel de la barra de menus quedo mas ajustado, y los textos en aleman e hindi los corrigio alguien que noto que el aleman cambiaba de persona gramatical a media frase.

Soundshine Record 1.1: veinticuatro correcciones en captura, grabacion, licencias e interfaz. Le corri un barrido adversarial de bugs, que es cuando le entrego el codigo a un revisor cuyo unico trabajo es encontrar cosas rotas y negarse a quedar tranquilo. Encontro veinticuatro. La version 1.0 llevaba tres dias publicada en ese momento.

El sitio de Portie: tenia treinta y nueve paginas separadas, una por numero de puerto, cada una delgada y ninguna posicionando. Ahora son un solo centro de referencia consolidado, con las URLs viejas redirigidas a los anclajes correctos. Tambien corregi una afirmacion que llevaba meses haciendo sobre el puerto 5000: en un Mac quien lo ocupa es el receptor de AirPlay, no un framework web que arranque ahi por defecto.

El sitio de Ejecta: el mismo tratamiento, reorientado a las preguntas que la gente de verdad hace clic en vez de las que yo asumia que escribia, y replicado a otros once idiomas.

El sitio de Decant: la base de SEO que nunca tuvo, mas la primera guia orientada a busqueda, localizada al español, portugues, japones, aleman, frances e italiano.

Freesend: cabeceras personalizadas en el endpoint de envio, y ahora devuelve el Message-ID real para que las respuestas se agrupen bien en el hilo.

CostKit: una caceria adversarial de bugs que saco problemas en facturacion, autenticacion, invitaciones de equipo y la generacion de PDF. Cinco eran lo bastante graves para arreglarlas al momento. Clasifique las treinta restantes por severidad con la intencion de volver despues, luego me dio rabia y arregle casi todas el mismo dia. La bateria de pruebas paso de 512 a 560.

Abner: el fragmento de seguimiento que genera mi servidor MCP estaba incrustando el identificador equivocado, lo que significaba que varios de mis sitios no registraban absolutamente nada. Todos los sitios que revise estaban afectados. Corregido, y los sitios vuelven a reportar.

Nada de eso es un lanzamiento. Todo eso es trabajo.

Blindfold se comio el resto

Blindfold es mi bloqueador de anuncios y rastreadores para iPhone y iPad. Salio a finales de julio. El bloqueo de contenido en Safari ha funcionado desde el primer dia. La funcion que se llama Everywhere, que bloquea en todas las apps y no solo en Safari, es la parte que lleva peleando conmigo desde entonces.

La primera version usaba un tunel de paquetes para filtrar DNS. Ese es el truco estandar: declaras una VPN, enrutas el DNS a traves de ti mismo, y descartas las peticiones que no te gustan. App Review lo rechazo bajo la directriz 2.5.1, uso no aprobado de NEVPNManager. Es justo, no es realmente una VPN.

Asi que lo migre a un proveedor de proxy DNS, que es la API que Apple aprueba para exactamente esto, y lo lance. Despues lei la nota tecnica con calma. Los proxies DNS solo corren en dispositivos supervisados, es decir dispositivos inscritos en gestion de dispositivos moviles. En un telefono que alguien compro en una tienda, la extension simplemente nunca se activa. Habia lanzado una funcion que no podia funcionar, para nadie, nunca. Eso es lo peor de este post y es enteramente culpa mia por construir sobre una API antes de leer sus requisitos de despliegue.

Esa sigue siendo la version que esta hoy en el App Store, con interruptor y todo, que no es una frase que disfrute escribir. Ya construi la version que lo desactiva con honestidad, con una explicacion de “en proceso de mejora” en lugar de un interruptor que finge, y esta subida. Todavia no esta adjunta a ningun lanzamiento, lo que significa que tal como estan las cosas ahora mismo no le sirve a nadie. Eso encabeza mi lista de esta semana.

El reemplazo es la API de filtro de URL de Apple, y aqui es donde se salio de control. Filtrar URLs a nivel de sistema significa que el dispositivo tiene que preguntarle a un servidor si una URL esta en una lista de bloqueo. Apple, con razon, no quiere que tu aprendas que URLs visita una persona. Asi que la consulta pasa por recuperacion privada de informacion: el dispositivo pregunta de una manera que es matematicamente incapaz de revelar que pregunto.

Esa es una propiedad preciosa. Tambien significa que si quieres lanzar esta funcion, no te toca llamar a una API. Te toca operar el servicio, permanentemente, mientras la app exista.

Asi que ahora opero tres piezas de infraestructura para un bloqueador de anuncios:

  • Un servicio PIR en Cloudflare Containers en pir.getblindfold.app, que sirve una lista de bloqueo procesada de 91,294 entradas mas un prefiltro Bloom para que el dispositivo se salte la consulta cara la mayoria de las veces.
  • Una pasarela Oblivious HTTP en gateway.getblindfold.app, porque el relevo de Apple reenvia peticiones encapsuladas que algo tiene que desencapsular.
  • Un emisor de Privacy Pass en su propio subdominio, para que los dispositivos puedan autenticarse sin quedar identificados.

Cada una de esas cosas es algo que nunca habia desplegado. Ademas, el proceso de Identidad y Confianza de Apple tiene que aprobar la configuracion del filtro de URL en si, y hasta que lo haga, lo mas probable es que una compilacion de lanzamiento falle la validacion. Eso entro en revision a finales de julio y sigo esperando.

Tambien construi una autoprueba dentro de la app, porque el problema honesto de un bloqueador que preserva la privacidad es que ninguno de los dos puede verlo funcionar. Blindfold ahora consulta un host canario que deberia estar bloqueado y un host de control que no deberia estarlo, y reporta el resultado. Si el bloqueado falla y el de control tiene exito, te dice “bloqueo confirmado”. Si no lo puede determinar, te lo dice, en vez de mostrarte una luz verde que no se ha ganado. La semana pasada corregi una mentira relacionada: un filtro que no habia logrado arrancar se mostraba como “iniciando”, para siempre.

Y se exactamente donde esto se rompe. El servicio PIR guarda las claves de evaluacion de cada usuario en memoria del proceso, lo que topa el despliegue entero en unos 1,300 usuarios y pierde todas las claves al reiniciar. Ese es un problema que me toca tener si la app tiene exito, y me gustaria tenerlo.

Un servidor que tengo que operar para siempre tambien hay que pagarlo para siempre, y eso cambia lo que Blindfold tiene que costar. Los precios originales asumian una app que no le habla a nadie. Esta tiene una factura de infraestructura permanente mientras haya un solo cliente usandola, y una compra de por vida tiene que cubrir de verdad su parte de eso. Ya tengo los numeros nuevos resueltos y los voy a publicar como corresponde, en el sitio de la propia app, en vez de enterrar una subida de precio a media de un post sobre estar cansado.

Blindfold 1.0.1 no ha salido. Yo mismo lo retire de revision en cuanto entendi que el proxy DNS era un callejon sin salida, porque lanzarlo habria significado lanzar la cosa rota dos veces. Desde entonces aterrizo una correccion de crash al arrancar en frio, y las dos estan ahora esperando el mismo lanzamiento. La version 1.0 sigue publicada y sigue bloqueando en Safari.

Esperando en la fila

Cosas que estan terminadas pero no en tus manos:

Leelo 1.1: enviado el domingo, esperando revision. Importar un EPUB paso de 212 segundos a 2.9. Las explicaciones de palabras ahora usan generacion guiada, guardan sus resultados en cache, y se recuperan cuando el modelo en el dispositivo rechaza una palabra en vez de simplemente fallar. Tambien borre 23,000 lineas de codigo muerto.

Just Habits 1.5: la compilacion 11 esta subida y adjunta, las notas de version escritas en quince idiomas, y esta bloqueada por que yo despliegue un cambio de esquema de CloudKit a produccion. Agrega notas por habito, y unas notas que no se sincronizan son peores que no tener notas, asi que espera. Tambien lleva dieciocho correcciones de rendimiento de una auditoria de bloqueos de interfaz.

Train531: un temporizador de descanso que corre como Live Activity, un contrato de comunicacion con el reloj que impide que un toque viejo registre una serie que nunca ocurrio, y una correccion de sincronizacion para que una copia remota desactualizada ya no pueda borrar un entrenamiento que tienes a medias. Todavia sin enviar.

SongSplit AI: separacion por lotes de carpetas enteras en macOS. Todavia sin enviar.

Lo que viene: Message Album

La nueva es Message Album, en messagealbum.com.

Exporta una sola conversacion de Mensajes desde tu Mac a un archivo privado, buscable y sin conexion. No es una copia de seguridad. Una copia de seguridad restaura un dispositivo; no te entrega la conversacion. Message Album te da una carpeta con un index.html que abres en cualquier navegador, los dos lados del hilo, cada foto, video y nota de voz que este de verdad en el Mac en calidad original, transcripciones en JSON y Markdown, y un manifiesto de sumas SHA-256 para que dentro de diez años puedas demostrar que la copia que tienes en la mano es la que salio. Lo que iCloud todavia no haya descargado aparece como una advertencia explicita en vez de quedar fuera calladamente.

Lee tu biblioteca de Mensajes en modo solo lectura y nunca la modifica. Tambien puede sacar una conversacion de una copia de seguridad de iPhone hecha con Finder, cifrada o no. No hay cuentas, ni telemetria, ni una sola peticion de red. Se vendera directamente desde su propio sitio, porque leer tu biblioteca de Mensajes requiere Acceso Total al Disco y eso no es algo que una app de la Mac App Store pueda tener.

Todavia no le pongo precio ni fecha. El precio sigue siendo literalmente un marcador de posicion en mi propio archivo de configuracion, y prefiero no decirte nada antes que decirte algo que tenga que retirar despues.

Sobre estar cansado

Aqui esta la cuenta. Treinta y seis productos este año, y esta es la semana treinta y tres. Mas productos que semanas. Sigo en ritmo para cincuenta y dos.

Deberia sentirme bien con eso, y en general asi es. Pero el numero que sube no es el numero que cuesta algo. Lanzar la app treinta y siete ya es una cantidad conocida. Mantener treinta y seis con vida es la parte de la que nadie me advirtio, y es la parte que no aparece en un post de lanzamiento. Soundshine tenia un bug de corrupcion. Blindfold necesitaba un servidor. Abner llevaba tiempo sin registrar nada. Portie tenia treinta y nueve paginas que debieron ser una. Nada de eso es glamoroso, todo eso es real, y cada semana que le dedico es una semana en la que el contador no se mueve.

Cuando escribi el post del reto en febrero, lo que intentaba arreglar era que nunca terminaba nada. Mi disco duro era un cementerio de prototipos. Ese problema esta resuelto. A fondo. El problema nuevo es que terminar algo no es el final de ese algo, y yo construi un marcador que solo premia el comienzo.

Asi que la regla cambia, un poco y con honestidad: una actualizacion sustancial de algo que ya vendo cuenta como el lanzamiento de esa semana. No un cambio de numero de version, no una correccion de erratas. Algo que un usuario notaria.

Con ese criterio el martes pasado si estaba cubierto. Soundshine 1.3.3 y Record 1.1 salieron el viernes anterior, y veinticuatro correcciones mas un bug de corrupcion no son un error de redondeo. Hoy no esta cubierto, y no voy a discutirlo. Todo lo que termine esta semana es infraestructura y sitios web. Ni una sola linea cambio una app que alguien ya tenga instalada. Uno de dos, bajo una regla que escribi yo mismo, que es el calificador mas indulgente que voy a conseguir jamas.

Prefiero tener una regla exacta antes que una heroica que rompo en silencio y luego vengo a disculparme.

La otra cosa que voy a hacer es descansar, que lo digo aqui sobre todo para hacerlo de verdad.

El proximo martes pienso tener Message Album afuera. Si no, tambien te lo dire.

← Volver a la lista