Commit Graph
487 Commits
Author SHA1 Message Date
chemavxandClaude Opus 5 f0e99635bf CLAUDE.md: el auto-reinicio ahora falla en cerrado y con permisos por nombre
Anade tambien como leer por que rama fue una ejecucion cuando
EXECUTIONS_DATA_SAVE_ON_SUCCESS=none ya la ha vaciado: por la duracion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 08:08:50 +00:00
chemavxandClaude Opus 5 50f090bbea Cerrar el auto-reinicio: fail-closed, permisos por nombre y fallo visible
Tres agujeros que encontro una review adversarial de Codex sobre el trabajo
de ayer. Los tres verificados contra el fichero antes de tocar nada.

1. El webhook publico fallaba en ABIERTO. Con `optional: true` y un
   `if (secreto && ...)`, la ausencia del secreto equivalia a autorizacion:
   cualquier POST con heartbeat.status=0 y un monitor.name del mapa reiniciaba
   n8n, Gitea, ArgoCD, Vaultwarden o los blogs. El argumento para dejarlo asi
   era "que un despiste no te deje sin avisos", y era falso: el aviso de caida
   lo manda Kuma por su notificacion 1, directa, no por este webhook.
   Ahora el secreto es obligatorio (sin `optional`) y la puerta rechaza si
   falta. Secreto ausente da error ruidoso; cabecera que no casa, vacio.

2. El ClusterRole permitia patch sobre CUALQUIER deployment de 10 namespaces,
   y la SA va montada en el pod entero de n8n: cualquier workflow con un nodo
   Code heredaba eso. Ahora son Roles por namespace con resourceNames sobre
   los 12 workloads exactos del SERVICE_MAP.

3. El flujo daba exito aunque el PATCH fallara. `restartOk` se calculaba y se
   tiraba: `K8s API Check Status` construia un objeto nuevo sin el, y el IF
   final solo miraba `statusOk`. Un 403 sobre un servicio ya sano mandaba
   "reiniciado correctamente". Ahora hay rama de fallo tras el PATCH y el
   exito exige observedGeneration >= la generation que devolvio el PATCH.
   Se compara con >= porque selfHeal de ArgoCD revierte la anotacion y vuelve
   a subir la generation; con == daria un fallo falso.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 08:02:07 +00:00
chemavxandClaude Opus 5 6454b56fe3 CLAUDE.md: las trampas que enganan al mirarlas
Este directorio es el WorkingDirectory de hermes-bot, o sea el sitio donde un
agente lee el contexto del cluster, y no tenia ninguno.

Se ha notado hoy: tras poner EXECUTIONS_DATA_SAVE_ON_SUCCESS=none en n8n, las
ejecuciones exitosas quedan como status='running' con deletedAt puesta hasta que
pasa el barrido. Hermes las vio, las tomo por ejecuciones colgadas y se gasto un
turno entero de quince minutos diagnosticando una averia inexistente en un
workflow que corria clavado cada cinco minutos.

Solo van aqui las cosas que enganan: lo que parece roto y no lo esta, y lo que
parece inofensivo y no lo es. El resto sigue en el skill k8s-infra.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 21:03:59 +00:00
chemavxandClaude Opus 5 125cdc9de0 n8n: cerrar el webhook del auto-reinicio con un secreto compartido
/webhook/uptime-kuma-restart es publico y sin autenticar. Mientras no reiniciaba
nada daba igual; desde hoy reinicia doce servicios, los dos blogs incluidos, asi
que cualquiera que diera con la ruta podia zarandear el cluster.

Uptime Kuma manda ahora la cabecera X-Kuma-Token (webhookAdditionalHeaders de la
notificacion "n8n Auto-Restart") y el primer nodo Code la compara con
KUMA_WEBHOOK_TOKEN antes de hacer nada.

La comprobacion falla en ABIERTO si el secreto no esta configurado en n8n: un
despiste de configuracion degrada al comportamiento de antes en vez de dejar de
avisar en silencio, que es el fallo que no se ve venir. Si esta configurado y no
coincide, se devuelve vacio: ni reinicio, ni Telegram, ni fila de error que se
pueda llenar a base de peticiones.

El secret n8n-kuma-webhook se crea con kubectl y NO esta en git; el env va con
optional: true para que la ausencia no impida arrancar el pod.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:25:17 +00:00
chemavxandClaude Opus 5 9d42dac312 argocd: excluir los exports de workflow de la app n8n
Una Application de tipo directorio lee *.yaml, *.yml y *.json indistintamente,
asi que la copia del workflow que acabo de meter en n8n/ entraba como si fuera
un manifiesto y dejaba la app en ComparisonError: "Object 'Kind' is missing".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:20:18 +00:00
chemavxandClaude Opus 5 cbfbc8bf16 n8n: copia en git del workflow del auto-reinicio
Los workflows viven solo en la SQLite, que ya se revirtio sola una vez (16-jul,
a un snapshot de abril) y se llevo por delante mes y medio de trabajo. Este en
concreto es el que reacciona a las caidas, asi que conviene tenerlo fuera.

Ya no hay nada secreto que ocultar: los tres nodos de Telegram leen el token de
$env.TELEGRAM_BOT_TOKEN en vez de llevarlo incrustado.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:19:20 +00:00
chemavxandClaude Opus 5 07521216c7 n8n: el auto-reinicio alcanza tambien a los dos blogs
Ghost EN y ES son lo unico del mapa que da la cara al publico y lo que peor se
lleva con dos semanas sin nadie mirando. Entran en el SERVICE_MAP con la clave
igual al nombre exacto del monitor de Kuma.

El monitor "www.zonadeexclusion.com (301->apex)" se queda fuera a proposito:
que ese 301 falle es cosa de Traefik o del DNS, no de Ghost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:15:08 +00:00
chemavxandClaude Opus 5 440eb5b6a1 n8n: dar permisos de reinicio al auto-restart de Uptime Kuma
El workflow "Uptime Kuma -> K8s Auto-Restart" lleva desde siempre sin poder
reiniciar nada: hacia el PATCH con el token de la ServiceAccount "default" del
namespace, que no tiene ni un permiso, y el API contestaba 403. Se iba entonces
por la rama de "reinicio fallido" y mandaba el aviso por Telegram -- que se
enviaba bien, y por eso los 23 "exitos" de workflow_statistics. La integracion
parecia viva y no lo estaba.

SA propia (n8n-restarter) en vez de la default, y un RoleBinding por namespace
en lugar de un ClusterRoleBinding: el webhook que dispara esto es publico y sin
autenticar, asi que el alcance se limita al SERVICE_MAP del workflow.

El ClusterRole incluye get ademas de patch porque el workflow relee el objeto a
los 60 s para comprobar readyReplicas (sin get: "Cannot read properties of
undefined"), y statefulsets ademas de deployments porque Gitea es lo primero.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 19:58:29 +00:00
chemavx 3112f92fea n8n: permitir modulos internos de Node en los nodos Code
Tres workflows ACTIVOS fallaban con "Module 'https' is disallowed" sin que
saltara ninguna alerta, porque estaba NODE_FUNCTION_ALLOW_EXTERNAL (paquetes
npm) pero no NODE_FUNCTION_ALLOW_BUILTIN (modulos internos):

  - Uptime Kuma -> K8s Auto-Restart  ultimo exito 2026-07-23 07:51
  - TLS Certs -> Alerta Telegram     ultimo exito 2026-04-13
  - Resumen Diario - Metricas K8s    30 fallos, 0 exitos

Es decir: el auto-reinicio que dispara Uptime Kuma llevaba una semana
muerto. Se rompio al reiniciarse el pod la tarde del 23-jul, cuando el task
runner empezo a bloquear require() de modulos internos.

Lista explicita (fs,http,https) en vez de '*': es justo lo que piden los
nodos Code de esos workflows, y asi un modulo nuevo falla a la vista en vez
de estar concedido de antemano.
2026-07-30 16:56:50 +00:00
chemavx c48ea74878 n8n: no guardar el payload de las ejecuciones exitosas
La poda por edad ya estaba activa de serie (n8n 2.15.1, prune=true, 336 h):
los IDs de ejecucion empiezan en 22.634 con 7.052 filas, o sea que ya habia
borrado ~22.600 el solo. El tar diario crecia 0,4 MB/dia y estaba llegando a
meseta, asi que no habia desbocamiento: la premisa era falsa.

El problema real era la composicion. De 322 MB de execution_data, 246 MB
(76%) eran las 3.436 ejecuciones EXITOSAS de 'Real Madrid RSS -> Twitter',
que corre cada 5 min y guarda 73 KB por vuelta. Sus errores -lo unico que
sirve para depurar- ocupaban 2 MB.

Y no es un problema de disco (21%, 699 GB libres) sino de backup: n8n esta
en CROWN, asi que ese .tar.gz de 101 MB viajaba entero a MEGA cada dia y a
B2 en las dos ultimas copias. Es justo el gasto que revento la cuota el
2026-07-25.

Nada depende de ese historico: el monitor de reversion solo lee
workflow_entity, el panel de Grafana mira replicas del deployment y
'Resumen Diario' saca metricas de k8s por un nodo Code.
2026-07-30 16:30:34 +00:00
Gitea CI 7dce3c43f6 ci: update researchowl image to 8b81ef87 [skip ci] 2026-07-30 10:14:53 +00:00
Gitea CI 859d80242e ci: update roswell-corpus image to 1005cab3 [skip ci] 2026-07-28 16:08:00 +00:00
Gitea CI 747db8579a ci: update roswell-corpus image to d838837b [skip ci] 2026-07-28 16:03:39 +00:00
Gitea CI 56cc4d6c1c ci: update roswell-corpus image to 6b3eb8cf [skip ci] 2026-07-28 16:01:14 +00:00
Gitea CI ec67146149 ci: update roswell-corpus image to b9e597af [skip ci] 2026-07-28 15:57:52 +00:00
Gitea CI 58cd3425a1 ci: update roswell-corpus image to 99fb7da1 [skip ci] 2026-07-28 15:55:49 +00:00
Gitea CI 4380e2f696 ci: update roswell-corpus image to 2a415354 [skip ci] 2026-07-28 15:53:58 +00:00
Gitea CI eb14115a89 ci: update roswell-corpus image to 14a8257c [skip ci] 2026-07-28 15:51:46 +00:00
Gitea CI 42627d3395 ci: update roswell-corpus image to b31562f3 [skip ci] 2026-07-28 15:40:43 +00:00
Gitea CI 197a32c07d ci: update roswell-corpus image to 4ba68021 [skip ci] 2026-07-28 15:35:18 +00:00
Gitea CI d05bf0d5ae ci: update roswell-corpus image to de3b2e34 [skip ci] 2026-07-28 15:26:22 +00:00
Gitea CI faafba1869 ci: update roswell-corpus image to e9476a63 [skip ci] 2026-07-28 15:17:59 +00:00
Gitea CI 6ebad58434 ci: update roswell-corpus image to 03b0d9a7 [skip ci] 2026-07-28 14:51:23 +00:00
Gitea CI 59d7d6b86c ci: update roswell-corpus image to 0dd1ef38 [skip ci] 2026-07-28 14:06:05 +00:00
Gitea CI 50398bb3f8 ci: update roswell-corpus image to e25e27e5 [skip ci] 2026-07-28 13:54:33 +00:00
Gitea CI 6047333230 ci: update roswell-corpus image to e6afe7d1 [skip ci] 2026-07-28 13:42:36 +00:00
Gitea CI ca5b27a1cc ci: update roswell-corpus image to b9bdeef2 [skip ci] 2026-07-28 13:35:32 +00:00
Gitea CI fa9f3c32ed ci: update roswell-corpus image to 4c2b40fe [skip ci] 2026-07-28 13:27:18 +00:00
Gitea CI 7f56a6ad2e ci: update roswell-corpus image to d8154523 [skip ci] 2026-07-28 12:28:32 +00:00
Gitea CI 6c9c529986 ci: update roswell-corpus image to 8181cca6 [skip ci] 2026-07-28 12:20:39 +00:00
Gitea CI 878ae4855a ci: update roswell-corpus image to 4b02af00 [skip ci] 2026-07-28 12:01:03 +00:00
Gitea CI b66deb9766 ci: update researchowl image to a43bbc75 [skip ci] 2026-07-28 05:39:50 +00:00
Gitea CI 939b535134 ci: update roswell-corpus image to 4b757c08 [skip ci] 2026-07-28 05:39:44 +00:00
chemavx 58cf9cdf8a roswell: volver a FEED_CHECK_HOURS=24, el atraso está drenado
El pase de las 04:58 UTC dejó todos los feeds a 0 pendientes, así que la
bajada temporal a 3 h del commit 134449e ya no hace falta. En régimen
normal entra ~1 episodio al día: revisar cada 3 h solo repetiría la
descarga del RSS ocho veces para no encontrar nada.

El comentario deja de ser un aviso pendiente y pasa a explicar por qué 24
es lo correcto y cuándo conviene volver a bajarlo.
2026-07-28 05:37:23 +00:00
chemavxandClaude Opus 5 d9f6a61c6a backup: quitar el --exclude de reddit-intel, ya no protege nada
Las copias remotas se purgaron a mano el 2026-07-27 (8 objetos en Mega, 3 en
B2, con --mega-hard-delete y --b2-hard-delete para que no se queden en papelera
ni como versiones ocultas). Sin subdirectorio remoto que preservar, el exclude
solo era ruido en la orden.

Verificado: el ConfigMap parsea y los cuatro scripts pasan `sh -n`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 20:17:48 +00:00
chemavxandClaude Opus 5 b19bb4d414 auditoría: quitar la excepción de reddit-intel
Los manifiestos que amparaba ya no existen, así que la excepción solo podía
envejecer. La auditoría queda en 0 hallazgos nuevos y 4 esperados (antes 13:
los otros 8 eran precisamente reddit-intel inactivo).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 20:12:45 +00:00
chemavxandClaude Opus 5 6f8d699ac0 backup: retirar reddit-intel del sistema de copias
El servicio se decomisó (Reddit denegó el acceso a la API), así que su CronJob
de n97 estaría empaquetando cada noche un directorio que ya nadie escribe, y
backup-verify seguiría exigiendo una copia fresca que nunca va a llegar: en
tres días habría empezado a sumar ERRORS y a disparar la alerta por una avería
que no existe.

Se van el CronJob, el script reddit-intel.sh y su comprobación en verify.sh.
El `--exclude /reddit-intel/**` de rclone-mega SE QUEDA a propósito: sync es un
espejo exacto y quitarlo borraría de un tirón las copias que aún viven en Mega.
Se retirará cuando se decida purgar ese remoto a mano.

Verificado: el ConfigMap sigue parseando y los cuatro scripts pasan `sh -n`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 20:11:38 +00:00
chemavxandClaude Opus 5 e4e387d360 reddit-intel: retirar los manifiestos, el proyecto queda decomisado
Reddit nos ha denegado el acceso a la API —la misma respuesta que a
roswell-corpus—, así que la promoción a k3s que describía PROMOTION.md no va a
ocurrir nunca. Estos manifiestos nunca llegaron a aplicarse (el app-of-apps no
es recursivo y no había Application), así que quitarlos no cambia nada en el
clúster; el namespace vacío se ha borrado a mano.

El contenedor de n97 se paró el 2026-07-27 tras once días devolviendo 401, con
la base de datos vacía: nunca registró un solo post. Copia final en
~/decommissioned/reddit-intel-final-2026-07-27.tar.gz y el código sigue en su
repo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 20:09:40 +00:00
chemavxandClaude Opus 5 134449e6dc roswell: revisar feeds cada 3h mientras drena el atraso (TEMPORAL)
45 episodios pendientes = 33,8 h de audio ≈ 20 h de CPU, pero a una pasada
cada 24 h con tope de 5 el pod transcribía ~4 h y descansaba ~20: el atraso
tardaba 5 días. Con 3 h encadena pasadas y se va en algo más de un día.

No cambia el pico de memoria (sigue transcribiendo de una en una, y el
troceado en ventanas ya lo acotó). Revertir a 24 al terminar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 20:44:45 +00:00
chemavxandClaude Opus 5 e4b1d28da7 roswell: explicar por qué 8Gi ya no es una cifra perseguida
El límite subió 4→6→8Gi persiguiendo episodios largos porque el pico de
whisper escalaba con la duración. Con el troceado en ventanas (roswell-corpus
c869b61) el pico dejó de depender del episodio, así que 8Gi pasa de ser el
siguiente escalón a tener margen de sobra. Se deja escrito para que nadie lo
suba por inercia sin mirar antes si el troceado sigue vivo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 20:38:21 +00:00
Gitea CI c75d6d5491 ci: update roswell-corpus image to 993f54b0 [skip ci] 2026-07-26 20:33:17 +00:00
Gitea CI b6616a6fa7 ci: update roswell-corpus image to 74731e14 [skip ci] 2026-07-26 15:48:24 +00:00
chemavxandClaude Opus 5 4adbcbd4af vaultwarden y gitea pasan a ArgoCD
Los dos estaban en git sin ninguna Application que los gestionara: editar el
repo no desplegaba nada. De ahi que un pin de imagen de abril nunca llegara
al cluster y gitea se subiera solo de 1.25.5 a 1.27.0, y que vaultwarden se
parcheara con kubectl replace. A partir de ahora manda git.

Verificado en frio antes de adoptar: los 17 manifiestos coincidian campo a
campo con lo vivo, asi que la adopcion no revierte nada. Con
ServerSideApply/ServerSideDiff, igual que el kube-prometheus-stack: estos
objetos arrastran un last-applied viejo y el merge clasico intentaria borrar
lo que ese blob declaraba y git ya no; en un PVC eso es un campo inmutable y
el sync falla.

Limpieza que iba en el mismo paquete:

- Fuera la basura de export de 5 ficheros: last-applied-configuration, la
  revision del Deployment y las anotaciones que pone el provisionador en los
  PVC (bind-completed, selected-node...). Es lo que dejaba los recursos
  OutOfSync para siempre. Verificado que el resto del manifiesto no cambia.
- Fuera serviceaccount-default y kube-root-ca.crt de los dos: los crea k8s
  solo en cada namespace.
- RESCATADO configmap-gitea-runner-config: config del act_runner escrita a
  mano en abril, montada por el runner y que NO estaba en git. Reconstruir
  gitea desde el repo levantaba el runner sin configuracion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 20:42:38 +00:00
chemavxandClaude Opus 5 9719a6179a monitoring: avisar de que el alerting no se recarga solo
Las dos alertas de B2 llevaban desde esta manana en el ConfigMap y MUERTAS:
Grafana lee el provisioning de alerting solo al arrancar y el pod era del
dia 22. El sidecar de kiwigrid recarga dashboards y datasources, pero el
alerting entra por extraConfigmapMounts y ese camino no lo toca nadie.

Reiniciado Grafana: 7 reglas cargadas -> 9. Queda el aviso en la cabecera
del fichero, con el comando de reinicio y el de comprobacion contra la API,
que es la unica fuente de verdad aqui (el ConfigMap mentia).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 20:27:04 +00:00
chemavxandClaude Opus 5 64d306d1e3 monitoring: fuera de git los 49 manifiestos que no escribimos nosotros
43 eran el render del kube-prometheus-stack, volcados con kubectl get -o yaml
y sin que nadie los aplicara: decoracion que solo servia para creerse que git
describia el cluster. Ahora los genera el chart desde la Application de la
Fase 2, que es su unico dueño.

Los 6 restantes los fabrica un controlador y en git no pintan nada:
rulefiles-0 (154KB que genera el prometheus-operator desde los
PrometheusRule), el StatefulSet, el service prometheus-operated y el PVC de
datos (los tres nacen del CR Prometheus / su volumeClaimTemplate), mas
serviceaccount-default y kube-root-ca.crt, que k8s crea solo en cada
namespace.

Ninguno estaba en la lista blanca del app de monitoring, asi que borrarlos de
git no toca el cluster. Clasificados uno a uno antes de borrar (render del
chart vs ownerReferences vivas), no a bulto.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 20:22:27 +00:00
chemavxandClaude Opus 5 40205eddc3 monitoring: Fase 2, el kube-prometheus-stack pasa a ArgoCD
El chart era un release Helm gestionado a mano (helm upgrade) desde abril.
Ahora lo gestiona su propia Application con source Helm, version clavada a
83.2.0 (la que ya corria: esto es una adopcion, no una actualizacion).

Los valores se mudan de values-kube-prometheus-stack.yaml al valuesObject de
la Application, con sus comentarios: ahi esta el historial de los retoques a
mano que se recuperaron en julio (alerting, SSO de Authentik, token de
Telegram), y perderlo seria perder el mapa. Inline y no multi-source $values
porque ese montaje se auto-podo la Application de infisical el 2026-06-18, y
tener los valores en dos sitios es la deriva que veniamos a matar.

La adopcion se verifico ANTES de activar el auto-sync: aplicada sin
syncPolicy, ArgoCD daba 96/97 Synced sin haber sincronizado nunca. El que
faltaba era el Deployment de Grafana, y no por deriva: el render del subchart
no declara managed-by: Helm ni el restartedAt del podTemplate, asi que el
merge a 3 bandas del cliente los habria BORRADO (reinicio de Grafana + Helm
perdiendo la propiedad del objeto). Con ServerSideApply/ServerSideDiff ArgoCD
solo toca lo que declara: 97/97 Synced, cero operaciones de sync, cero pods
reiniciados. selfHeal probado con replicas 1->2 en kube-state-metrics,
revertido en 11s.

skipCrds: true a proposito: ArgoCD pasa --include-crds por defecto y los 10
CRD de monitoring.coreos.com no los gestiona nadie hoy. Contrapartida
documentada en el fichero: al subir de chart hay que aplicarlos a mano.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 20:22:27 +00:00
chemavxandClaude Opus 4.8 e26b8b95ad monitoring: quitar last-applied-configuration de los manifiestos propios
Basura del volcado con kubectl get -o yaml. Al estar versionada se muerde la
cola: ArgoCD la aplica, k8s genera una nueva que ya incluye el tracking-id, y
git y cluster no coinciden nunca -> los 4 recursos se quedaban OutOfSync para
siempre. Verificado que el resto del manifiesto queda byte a byte igual.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 15:40:01 +00:00
chemavxandClaude Opus 4.8 9d903775ac monitoring: Fase 1 bajo ArgoCD (solo los manifiestos propios)
Hasta ahora las alertas de Grafana se aplicaban a mano con kubectl apply,
asi que dependian de que alguien se acordara (se vio hoy al anadir las de B2).

Lista blanca explicita en vez del directorio entero: monitoring/ mezcla tres
duenos y solo uno es nuestro. Fuera quedan los ~40 renderizados del chart
kube-prometheus-stack (release Helm viva -> dos duenos del mismo objeto) y los
generados por controladores (rulefiles-0 del prometheus-operator, etc).
Adoptar el chart via source Helm queda como Fase 2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 15:36:13 +00:00
chemavxandClaude Opus 4.8 d45e0a7cad monitoring: alertas de cuota y versiones ocultas de B2
Gemelas de las de MEGA: avisan si B2 factura >80% de los 10GB gratis
(b2_billed_bytes) o si las versiones ocultas pasan de 2GB (b2_hidden_bytes,
lo que indicaria que algun borrado no usa --b2-hard-delete).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 15:17:14 +00:00
chemavxandClaude Opus 4.8 dab1a72e1c backup-system: --b2-hard-delete + exporter de uso real de B2
B2 tiene el mismo fallo que la papelera de MEGA con otro nombre: al
borrar/espejar no elimina, oculta la version vieja y la sigue facturando.
Las versiones ocultas llegaron al ~88% del tramo gratis de 10GB el
2026-07-25 (8.78 GiB facturados vs 1.75 GiB visibles).

- --b2-hard-delete en el sync de crown-jewels y en el delete de reddit-intel
- mega-quota-exporter ahora tambien exporta b2_visible/billed/hidden_bytes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 15:17:14 +00:00