Justine · Recovery Hub

Slagelse SL · Mac Mini macmini-justine · acceso restringido

Estado del sistema

USB-A
hace 6d
USB-B (offsite)
hace 6d
Audit chain
íntegra · usb_observability_fix_applied
Último verify_recovery
OK=11 WARN=0 CRIT=1 · hoy

Enlaces rápidos

Runbook

Justine Apartments / Slagelse SL — Disaster Recovery Runbook

> Audiencia: yo (Pedro) o cualquier persona técnica que tenga que rearmar el sistema cuando yo no esté disponible. > Fuente canónica de este documento: github.com/holaslagelse/slagelse-ops/RECOVERY.md > Versión: 1.0 — 2026-05-09 > Mantener también copia impresa en lugar físico seguro.


0. Glosario rápido

TérminoQué es
Mac Mini canónicoMáquina principal macmini-justine (Tailscale 100.68.196.112). Hosting: en casa de Pedro.
Time MachineBackup local horario en SSD Corsair montado como /Volumes/TimeMachine.
DriveCuenta Google hola.slagelse@gmail.com. Archivo histórico contable + facturas.
GitHubRepos privados slagelse-ops (código + docs) y cowork-skills (skills empaquetados).
KeychainAlmacén nativo macOS de secrets. 12 entries justine-* y beyondpricing.com.
1PasswordGestor de secrets recomendado como mirror del Keychain (pendiente de implementar).
USB RK_01Disco USB de disaster recovery con bootstrap completo. Skill: justine-recovery-remoto.
Justine-Backup-*.zipZIPs diarios runtime crítico generados a las 03:30. Local en ~/Library/Justine/backups/.

1. Antes de cualquier recovery: identificar el escenario

EscenarioSíntomaIr a sección
AMac Mini físicamente roto / robado / nuevo hardware§3
BMac Mini vivo pero código corrupto, scripts borrados§4
CDatos operativos perdidos (slagelse/data/ borrado o corrupto)§5
DSin acceso a Mac Mini, recuperar desde otra máquina (emergencia)§6
EBackup probado mensual (no es recovery real, pero hay que hacerlo)§7

2. Qué necesitas tener a mano antes de empezar


3. Escenario A: Mac Mini muere — hardware nuevo de cero

3.1 Hardware

3.2 Bootstrap macOS

1. Instalar última versión estable de macOS desde Apple. 2. Crear usuario agent (mismo nombre crítico para que paths sigan funcionando). 3. Instalar Xcode Command Line Tools:

``bash xcode-select --install ``

4. Instalar Homebrew:

``bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``

5. Instalar paquetes base:

``bash brew install python@3.12 git gh node tailscale gitleaks pre-commit rclone gnupg brew install --cask google-drive 1password ``

3.3 Conectar Tailscale


sudo tailscale up --authkey="$(security find-generic-password -s justine-tailscale-authkey -w)" --hostname=macmini-justine

Si no tienes el authkey: entrar en https://login.tailscale.com/admin/settings/keys con la cuenta del owner y generar uno nuevo.

3.4 Restaurar Time Machine (datos personales + apps + Library)

Conectar SSD Corsair, abrir Migration Assistant (/Applications/Utilities/Migration Assistant.app) y elegir "From a Time Machine backup". Seleccionar el último snapshot.

Esto recupera:

Smoke test post-restore:


ls -la ~/Documents/Claude/slagelse/scripts/ | head -5  # debe haber Python files
security find-generic-password -s justine-smoobu-api -w | head -c 10  # debe devolver token

3.5 Clonar GitHub (código fresh, fuente canónica de código)


mkdir -p ~/repos
cd ~/repos
gh auth login   # autenticar con cuenta GitHub
git clone git@github.com:holaslagelse/slagelse-ops.git
git clone git@github.com:holaslagelse/cowork-skills.git

3.6 Reconciliar GitHub vs Time Machine

El código en GitHub es canónico. Si Time Machine restauró una versión más reciente que GitHub, hacer commit del diff:


diff -r ~/repos/slagelse-ops/ ~/Documents/Claude/slagelse/ | head -40
# Si hay diff legítimo, commit en slagelse-ops

3.7 Reinstalar skills


~/repos/cowork-skills/tools/install_skills.sh

(Este script copia los .skill y descomprime en ~/.skills/skills/.)

3.8 Reinstalar LaunchAgents


~/repos/slagelse-ops/projects/recovery/install_launchd.sh

(Este script copia plists desde slagelse-ops/projects/<proyecto>/launchd/ a ~/Library/LaunchAgents/ y hace launchctl load.)

3.9 Reactivar Justine Agent y servicios


launchctl load ~/Library/LaunchAgents/com.justine.scheduler.plist
launchctl load ~/Library/LaunchAgents/com.justine.scheduler-watchdog.plist
launchctl list | grep justine

Confirmar que el daemon scheduler arranca y empieza a refrescar datos cada 30 min.

3.10 Reconectar Drive

Abrir Google Drive desktop con cuenta hola.slagelse@gmail.com. Esperar a que sincronice. Verificar que los symlinks de ~/Documents/Claude/Slagelse (1) y ~/Documents/Claude/_inbox_facturas apuntan correctamente.

3.11 Smoke tests funcionales


cd ~/repos/slagelse-ops
python3 projects/recovery/verify_recovery.py

Esperado: OK en cada check (Time Machine, Drive, GitHub, Keychain, scheduler, pipeline banking dry-run).

3.12 Comprobar tarea programada de cuadre diario

A las 06:00 del día siguiente debe llegar email diario a 73.pedro@gmail.com. Si no llega, revisar:


tail -100 ~/Documents/Claude/slagelse/logs/daily_email.log

4. Escenario B: código corrupto, datos OK


cd ~/repos/slagelse-ops
git status
git checkout main
git pull --rebase
git reset --hard origin/main   # solo si confirmas que descartas cambios locales
~/repos/slagelse-ops/projects/recovery/verify_recovery.py

Si el script Python específico está corrupto, hacer git checkout HEAD -- projects/banking/src/compute_bank_reconciliation.py.


5. Escenario C: datos operativos perdidos

Fuente más reciente: Time Machine.


tmutil latestbackup
# Restaurar carpeta data/ desde TM:
sudo rsync -aH /Volumes/.timemachine/<latest>/<path>/Documents/Claude/slagelse/data/ ~/Documents/Claude/slagelse/data/

Verificar:


python3 -c "import json; d = json.load(open('~/Documents/Claude/slagelse/data/guests_data.json')); print(len(d), 'reservations')"

Si Time Machine está corrupto, ir al ZIP diario:


unzip ~/Library/Justine/backups/Justine-Backup-2026-05-05_0330.zip -d /tmp/restore/

6. Escenario D: emergencia sin Mac

Opción 1: USB RK_01. Conectar el USB a cualquier Mac, seguir skill justine-recovery-remoto.

Opción 2: Cualquier Mac + GitHub + Drive + Keychain backup.


# En Mac prestado o nuevo:
git clone git@github.com:holaslagelse/slagelse-ops.git
git clone git@github.com:holaslagelse/cowork-skills.git
# Importar Keychain desde backup (1Password si existe)
# Conectar Drive cuenta hola.slagelse@gmail.com

Esto te da código + secrets + facturas/docs. Faltarían los datos operativos, que no son críticos para responder huéspedes pero sí para facturar correctamente. Para datos operativos, esperar a recuperar Mac Mini original o restaurar Time Machine en máquina nueva (escenario A).


7. Backup probado mensual

Cada primer sábado del mes, ejecutar:


cd ~/repos/slagelse-ops
./projects/recovery/test_recovery.sh

Este script:

1. Crea un Mac virtual mínimo (o carpeta sandbox). 2. Restaura Time Machine en él. 3. Clona GitHub. 4. Importa Keychain. 5. Corre verify_recovery.py. 6. Genera informe recovery_test_<fecha>.md. 7. Envía email con resultado.

Si el test falla, hay que arreglarlo ANTES del próximo backup probado.


8. Lista de tareas programadas (LaunchAgents) que deben quedar activas

Estas son las 15 plists activas que documenta MANIFEST.json. Cada una vive en slagelse-ops/projects/<proyecto>/launchd/:

PlistFrecuenciaProyectoFunción
com.justine.scheduleralwaysdata-refreshDaemon principal Justine
com.justine.scheduler-watchdogevery 5 mindata-refreshWatchdog del scheduler
com.justine.refresh-serverhourlyserver-agentRefresh agente server
com.justine.refresh-otahourlydata-refreshRefresh OTA reservations
com.justine.verify-otadailydata-refreshVerificación OTA
com.justine.audit-facturas-canonicaldailyinvoicingAuditoría facturas
com.justine.sync-facturas-canonicaldailyinvoicingSync facturas
com.justine.sync-canonical-to-mirrordailyinvoicingMirror facturas a Drive
com.justine.monitor-gbp-listingsdailyweb-seoMonitor Google Business Profile
com.justine.weekly-gbp-postweeklyweb-seoPost semanal GBP
com.justine.python-health-dailydailyopsHealth check Python
com.justine.python-health-monthlymonthlyopsHealth check mensual
com.slagelse.clasificar-facturasdailyinvoicingClasificar facturas
com.slagelse.pull-drive-inboxhourlyinvoicingPull inbox Drive
com.slagelse.sync-facturas-emaildailyinvoicingSync facturas vía email

Las plists con .disabled o .bak son obsoletas y NO deben re-instalarse.


9. Contactos de emergencia


10. Cuándo actualizar este documento

Última revisión: 2026-05-09 — Pedro Próxima revisión obligatoria: 2026-11-09

Contactos de emergencia

QuiénPara quéDónde
Clearcorp · Evacontabilidad Slagelse SLegb@clearcorp.es
Clearcorp · Cristinafiscal Slagelse SLcvg@clearcorp.es
DonDominiohosting + DNS justineapartments.comdondominio.com (login con cuenta titular)
Tailscaleadmin VPN meshlogin.tailscale.com/admin/
Google Drive admincuenta Drive operativahola.slagelse@gmail.com
GitHubrepos privados slagelse-ops / cowork-skillsholaslagelse (73.pedro@gmail.com)
CloudflarePages kintsugi + recovery, D1, DNSdash.cloudflare.com (cuenta titular)