Source document

Alojamiento: la organización PBSWORK como fuente canónica

Spanish text, transcribed from the repository. The unformatted source is hosting.md.

Qué ocurrió

La cuenta de GitHub PBSWORK-ORG quedó marcada (flagged) por el sistema antispam de GitHub. El síntoma es un fallo silencioso: la cuenta y todos sus repositorios pasan a devolver 404 a usuarios no autenticados, sin correo, sin aviso y sin entrada en el panel.

Lo insidioso es que el dueño es la única persona que no ve el 404. Con sesión iniciada todo funciona con normalidad, así que el repositorio parece público mientras está invisible para el mundo. Un enlace compartido en una respuesta, un paper o un LLM que lo citó deja de resolver, y no hay forma de enterarse salvo comprobándolo a propósito.

La decisión: mover el repositorio a la organización

La hipótesis de partida era que el flag afecta a la cuenta y no al contenido, así que bastaba con sacar el repositorio de la cuenta marcada y ponerlo bajo la organización PBSWORK (id 198443207, creada en 2025). Se verificó con PBSWORK/MESH_SILOS, que respondía 200 sin credenciales en ese momento.

Movimiento ejecutado (resultado real, no el previsto):

AntesDespués
github.com/PBSWORK-ORG/HECATE (404 público)github.com/PBSWORK/HECATE (404 público)
Cuenta personal marcadaOrganización también oculta a invitados
Remoto origin con el owner antiguogit@github.com:PBSWORK/HECATE.git

El nombre del repositorio no cambia, así que la URL final es github.com/PBSWORK/HECATE. Al no aceptar GitHub la transferencia, el contenido se replicó con git push: se conservan historial, etiquetas y releases, pero no los metadatos del panel (issues, PRs, estrellas) del repositorio original.

Importante: para trabajar, el flag es irrelevante. El titular, con sesión iniciada, crea repositorios, hace push, etiqueta, abre issues y ve todo con normalidad. La marca solo afecta a la visibilidad anónima, es decir, a cualquiera que abra la URL sin sesión. Por eso el repositorio es completamente funcional como entorno de desarrollo; lo que queda pendiente es que un desconocido pueda verlo.

Por qué no Codeberg

Una revisión anterior de este documento proponía Codeberg como fuente canónica. No se usó nunca: no existe cuenta ni remoto allí, y el titular solo tiene cuenta de GitHub. La propuesta se retiró de todos los metadatos (CITATION.cff, .well-known/ai.txt, llms.txt) para no publicar enlaces que no resuelven. Si algún día se añade un espejo, se decidirá con una cuenta real y se documentará aquí antes de tocar los enlaces.

Estado actual (honesto)

PasoEstado
1. Todo el trabajo publicado en el remoto antiguo antes de mover nadahecho (git push origin main --tags)
2. Transferencia PBSWORK-ORG/HECATE → PBSWORK/HECATE desde los ajustesrechazada por GitHub: 422 · Repository transfers not available for this account. Una cuenta marcada no puede transferir.
3. Alternativa ejecutada: repositorio vacío creado en la organizaciónhecho (PBSWORK/HECATE, público)
4. Historial y etiquetas empujados a la organizaciónhecho: 24 commits y v0.3.0–v0.6.0 verificados con git ls-remote
5. Remoto origin apuntando a la organizaciónhecho (git@github.com:PBSWORK/HECATE.git)
6. Enlaces públicos a github.com/PBSWORK/HECATEhecho en site/, pyproject.toml, Cargo.toml, CITATION.cff, .well-known/ai.txt y llms.txt
7. Comprobación sin credenciales de que la URL nueva resuelvedevuelve 404, que es el comportamiento esperado mientras la cuenta esté marcada
8. Apelación del flag en GitHub Supportpendiente, lo abre el titular de la cuenta

Estado del flag en 1.1.0 (2026-10-23)

Sigue marcada. No se ha apelado desde el agente y no se debe hacer: la apelación la abre el titular de la cuenta, con su identidad, desde GitHub Support. Un agente que enviara esa solicitud estaría hablando en nombre de una persona ante el sistema antispam de GitHub.

Consecuencia práctica, sin cambios: el desarrollo funciona entero con sesión iniciada; lo que no funciona es la audiencia sin sesión. Por eso docs/release-1.0.0.md y docs/benchmarks/final.md existen como documentos del repositorio y no sólo como páginas web: si nadie anónimo puede ver el sitio, los números tienen que poder leerse en el árbol.

Los ocho enlaces canónicos siguen apuntando a github.com/PBSWORK/HECATE. No se ha cambiado ninguno a la organización antigua.

Por qué el 404 anónimo no bloquea el trabajo

Mover el repositorio a la organización no ha cambiado la visibilidad anónima. Comprobado sin credenciales, después del traslado:

Consulta anónimaResultado
api.github.com/orgs/pbswork/repos200 y lista PBSWORK/HECATE y PBSWORK/MESH_SILOS como public
api.github.com/repos/PBSWORK/HECATE404
github.com/PBSWORK/HECATE404
github.com/PBSWORK (página de la organización)404
github.com/PBSWORK/MESH_SILOS404 — respondía 200 minutos antes del traslado
github.com/rust-lang/rust (control)200
Proxy externo sobre github.com/PBSWORK/HECATE404, confirmado desde otra red

La API de la organización sigue describiendo los repositorios como públicos mientras la web los oculta a los visitantes sin sesión. La consecuencia práctica es que el flag viaja con la identidad: cualquier namespace del titular, incluida la organización, queda oculto a guests. Crear el repositorio nuevo no lo empeoró de forma demostrable, pero tampoco lo arregló, y la hipótesis de que el flag era solo de la cuenta personal no se sostuvo.

Con sesión iniciada todo funciona: crear repositorios, push, etiquetas, issues y la web del proyecto. El flag no limita el desarrollo, solo la audiencia. Ese es el motivo por el que este detalle se documenta y no se trata como un bloqueante.

Lo que sí está resuelto, y no es poco: el contenido ya no vive en un único sitio. El historial completo, las cuatro etiquetas y el árbol de trabajo están replicados en un namespace distinto del marcado. La apelación deja de ser urgente para no perder trabajo.

Ningún script de este repositorio finge que la migración está hecha. just links reporta como no resolubles las URL que no responden, que es la verdad.

Detalle importante de orden: publicar antes de mover. Si se traslada con commits locales sin publicar, se pierden si algo sale mal; publicados, el traslado no puede llevarse por delante nada que no esté ya replicado.

Cómo se hizo el traslado

  1. git push origin main --tags contra el remoto antiguo, para que nada quedara solo en local.
  2. Settings → Danger Zone → Transfer ownership con destino PBSWORK. GitHub lo rechazó con 422: una cuenta marcada no puede transferir.
  3. Alternativa: crear PBSWORK/HECATE vacío (público, sin README ni licencia) desde la organización.
  4. git remote set-url origin git@github.com:PBSWORK/HECATE.git
  5. git push -u origin main y git push origin --tags.

Consecuencia de la alternativa: se conserva el 100 % del historial, pero no los metadatos del panel (issues, PRs, estrellas) del repositorio original. Y, como queda documentado arriba, la visibilidad anónima sigue dependiendo de la apelación.

Si la apelación no prospera

Un alojamiento cuyo modo de fallo es invisible no puede ser la única fuente pública. Las opciones, en orden de coste:

  1. Apelar (Account Questions → Appeal a flagged account). Es lo primero y lo único que devuelve la visibilidad anónima a la normalidad.
  2. Espejo en otra forja con una cuenta distinta de la marcada. Requiere crear esa cuenta; hasta entonces no se anunciará ningún enlace, porque un espejo que no existe es peor que ninguno.
  3. Publicación de artefactos por otra vía: el sitio en hecateforge.com (Cloudflare, no depende de GitHub) y los binarios como artefactos de release alojados fuera del repositorio.

La tercera vía ya está en marcha

El sitio se publica en Cloudflare Pages y ya sirve https://hecateforge.com sin pasar por GitHub: es la única pieza del proyecto que hoy es visible sin sesión y sin depender del flag. El manual de operación —despliegue, dominio, cabeceras y lo que queda pendiente— está en docs/hosting-cloudflare.md. Consecuencia práctica: mientras el flag dure, la web es el canal público y el repositorio es documentación de trabajo, no la cara del proyecto.

Publicar a partir de ahora

El remoto ya es la organización, así que cada release se publica una sola vez:

just audit                                  # la verificación de siempre
git tag -a v0.8.0 -m "v0.8.0 — ..."
git push origin main --tags

Comprobar con git remote -v que origin sigue en PBSWORK antes de etiquetar. Si alguien restaura el remoto antiguo por error, las etiquetas acabarían en el namespace marcado.

Lista de comprobación de publicación

Se recorre entera antes de cada push que publique algo, y se copia el resultado en el CHANGELOG. No es burocracia: el modo de fallo de este alojamiento es invisible, así que lo único que lo detecta es comprobarlo a propósito.

#ComprobaciónComandoCriterio
1Árbol limpio, sin cambios ajenos mezcladosgit status --porcelainvacío
2El remoto apunta a la organizacióngit remote -vPBSWORK/HECATE, no PBSWORK-ORG
3Los commits que se publican son los previstosgit log --oneline origin/main..HEADsólo los de esta publicación
4La suite pasa en localjust checkverde
5La auditoría de repositorio pasajust auditverde
6Los fixtures de paridad están al díajust fixture--check sin diferencias
7La versión es la misma en los cinco sitiosjust versionsCargo.toml, pyproject.toml, CITATION.cff, llms.txt, package.json
8La etiqueta es anotada y describe el cambiogit tag -a vX.Y.Z -m "..."git cat-file -t responde tag
9Publicar antes de mover nadagit push origin main --tagsgit ls-remote --tags origin lista la nueva
10Los enlaces públicos resuelven sin sesiónjust links2xx/3xx en todos
11El nombre del repositorio no depende de la persona que empujacurl -s -o /dev/null -w '%{http_code}' https://github.com/PBSWORK/HECATE2xx cuando el flag esté resuelto; 404 mientras no lo esté, y se reporta como tal

Los pasos 1–7 y 11 son los que evitan los cuatro fallos que ya han ocurrido en este proyecto: mezclar trabajo ajeno en un commit de release, etiquetar contra el remoto equivocado, publicar con los fixtures desactualizados y una versión distinta en cada metadato.

El nombre canónico no se negocia

PBSWORK/HECATE es el repositorio, y no se cambia. El remoto origin de todos los clones apunta ahí (git@github.com:PBSWORK/HECATE.git), los cinco metadatos lo declaran (Cargo.toml, pyproject.toml, CITATION.cff, .well-known/ai.txt, llms.txt) y el sitio enlaza ahí. Cualquier herramienta o panel que muestre otro propietario describe un estado transitorio del cliente, no una decisión del proyecto: la respuesta es comprobar con git remote -v, no reescribir URLs.

Mover los enlaces a otro namespace para que una comprobación salga en verde sería el peor cambio posible: rompería el remoto, la citación y los enlaces del sitio a la vez para satisfacer a una herramienta. Si algún día hay que cambiar de propietario, se hace como una migración —documentada aquí, con el contenido replicado y verificado antes de tocar un solo enlace— y no como un ajuste de texto.

Nota de estado (2026-10-23)

La comprobación anónima del paso 11 sigue devolviendo 404 en github.com/PBSWORK/HECATE y en github.com/PBSWORK/HECATE/releases, mientras la API de la organización lista el repositorio como público. Es el comportamiento descrito arriba: el flag oculta el namespace a los visitantes sin sesión aunque el contenido sea público. Se reporta como está y no se "arregla" cambiando URLs.

El duplicado se retiró (2026-10-28)

github.com/PBSWORK-ORG/HECATE ya no existe: el titular lo borró el 2026-10-28. La comprobación de que no se perdía nada se hizo antes de retirarlo, y se repite aquí porque es el motivo por el que el borrado fue seguro:

ComprobaciónResultado tras el borrado
git ls-remote https://github.com/PBSWORK-ORG/HECATE.gitfalla: el repositorio ya no existe
git ls-remote origin refs/heads/main67a3668, la release actual
git rev-parse HEAD en este clon67a3668, el mismo commit
git merge-base --is-ancestor db0bbe7 HEADsí — el último commit del duplicado estaba contenido
etiquetas v* en PBSWORK/HECATE27 publicadas; 28 en local, porque v1.9.0-final es local a propósito

El duplicado tenía una sola rama main en db0bbe7 —«mueve el owner canónico a la organización»— y ninguna etiqueta v2.x: era el original que se replicó, no una copia que recibiera trabajo. Por eso git merge-base --is-ancestor db0bbe7 HEAD respondía que sí, y borrarlo no perdió ni un commit. refs/heads/main en PBSWORK/HECATE siguió en la release actual durante todo el proceso.

La vía reversible que documentaba esta sección —*Archive this repository* en lugar de Delete— ya no aplica: el repositorio está eliminado. Si alguna vez hay que volver al estado anterior, el contenido está en PBSWORK/HECATE, que es el canónico y el único remoto.

Una consecuencia que conviene tener presente: git ls-remote contra el namespace borrado ahora falla. La asimetría que se documentaba aquí —el protocolo git servía el namespace marcado aunque la web diera 404— sólo era válida mientras el repositorio existía, así que ya no sirve como forma de auditar el namespace de la cuenta personal sin credenciales.

Sobre Codeberg

No queda ninguna URL a Codeberg: ni en el código, ni en los metadatos, ni en el sitio. La comprobación es git grep -rn 'codeberg\.', que no devuelve nada —git grep -ri codeberg sí devuelve estas líneas y las del CHANGELOG, que son la explicación de por qué no se usó, no un enlace—. Las menciones originales se retiraron en la fase 7. La regla vigente es: GitHub es el único remoto, y el nombre canónico es github.com/PBSWORK/HECATE hasta que la comprobación del paso 11 diga otra cosa.

Auto-auditoría mensual

El fallo es silencioso, así que hay que comprobarlo a propósito. Desde una sesión no autenticada —ventana privada, o curl sin credenciales— los enlaces deben resolver:

just links
# o a mano:
curl -s -o /dev/null -w '%{http_code}\n' https://github.com/PBSWORK/HECATE
curl -s -o /dev/null -w '%{http_code}\n' https://hecateforge.com

scripts/check_hosting_links.py automatiza esto: recorre los enlaces públicos declarados en llms.txt, ai.txt, CITATION.cff y README.md, los pide sin credenciales y falla si alguno no responde 2xx/3xx. Detecta los tres casos que duelen:

  • una cuenta o un repositorio marcado (404 en el canónico),
  • un enlace a un destino que todavía no existe (404 en una migración a medias),
  • un enlace interno que apunta a un fichero que ya no existe.

No está en just check ni en scripts/verify.sh porque necesita red: la regla del proyecto es que la verificación obligatoria funcione sin conexión. Es una tarea manual mensual, y la primera del mes.

Lección para el diseño

Un alojamiento con fallo silencioso obliga a tener un plan que no dependa de él:

  1. La fuente canónica no puede ser un servicio cuyo modo de fallo sea invisible.
  2. Un namespace marcado se abandona, no se espera: el contenido sano se muda a uno que no lo esté.
  3. Todo enlace público debe ser comprobable sin la sesión del dueño; si no, no hay auditoría posible.
  4. El proyecto debe seguir siendo verificable y clonable sin su forja: de ahí que la verificación sea local y que los metadatos (CITATION.cff, llms.txt) viajen en el propio repositorio y no en un panel externo.