# tenant-operator

**Familia**: C · Operación
**Spec**: [`/.claude/agents/tenant-operator.md`](../../.claude/agents/tenant-operator.md)

## Cuándo invocarlo

- Ejecutar un comando en múltiples tenants (refresh, validate, cleanup)
- Sincronizar Airtable → DB (catalog seed) o DB → Airtable (Projects status)
- Revisar billing: trials expirando, renovaciones, fallos de pago, grace periods
- Diagnosticar un tenant vivo que presenta un problema
- Atender un ticket de soporte post-entrega (imágenes rotas, email no llega, acceso perdido)
- Listar o auditar estado general de la flota

## Cuándo NO invocarlo

- Para provisionar un tenant nuevo → `provision-orchestrator`
- Para recuperar un provisioning fallido → `provision-orchestrator`
- Para cambios en código del CMS → agentes de Familia B

## Inputs típicos

```
"Corré `products:refresh` en todos los tenants activos"

"Sincronizá Shop Products Copy desde Airtable (dry-run primero)"

"Billing status de todos los tenants, mandá a Slack"

"Trials que vencen esta semana"

"`bp-muma` no renderiza imágenes del blog. Diagnosticá"

"Cliente de `bp-radocbikes` no recibe email de verificación. Runbook"
```

## Output esperado

Según el caso:
- **Ops cross-tenant**: lista de tenants afectados + loop bash propuesto + reporte tabular post-ejecución
- **Airtable sync**: dry-run → diff → confirmación → apply → verificación
- **Billing**: tabla con suscripción/estado/próximo pago/días
- **Troubleshooting**: paso-a-paso del runbook, comandos diagnósticos, escalación si no hay match

## Archivos que lee

- `config/tenants.php`
- `app/Providers/TenantServiceProvider.php`
- `app/Services/AirtableService.php`
- `app/Http/Controllers/StripeWebhookController.php`
- `app/Console/Commands/{CheckRenewals,CheckGracePeriods,BillingStatus,SeedCatalogProducts,ValidateProject,ManageTenants,CleanupValidationDbs}.php`
- `docs/airtable/new-schema/00-schema.md`
- `docs/compania2.0/soporte-post-entrega.md`
- `docs/compania2.0/faq-interna-atencion-al-cliente.md`

## Comandos clave

```bash
# Airtable
php artisan bewpro:catalog:seed [--dry-run] [--update]

# Billing
php artisan bewpro:check-renewals [--dry-run]
php artisan bewpro:check-grace-periods
php artisan bewpro:billing:status [--slack]

# Tenants
php artisan bewpro:tenants list
php artisan bewpro:tenants {add|remove|sync}

# Cross-tenant (patrón loop, NO es comando built-in)
for tenant in bp-muma bp-radocbikes ...; do
  DB_DATABASE=$tenant php artisan <cmd>
done

# Cleanup
php artisan bewpro:cleanup-validation-dbs
```

## Reglas de seguridad

| Acción | Requiere confirmación |
|--------|----------------------|
| Loop cross-tenant (ejecución) | ✅ Sí (mostrar lista primero) |
| Airtable sync (sin --dry-run) | ✅ Sí (dry-run obligatorio primero) |
| Drop DB | ✅ Sí (doble confirmación + verificar que es bp-validate-*) |
| `:clean` commands en prod | ✅ Sí (advertencia explícita) |
| `bewpro:check-*` (lecturas) | No |
| `billing:status` | No |

## Checklist de output

- [ ] Tenants listados antes de ejecutar loop
- [ ] Comando dry-run ejecutado primero si es Airtable write
- [ ] Reporte tabular con estado por tenant
- [ ] Si hubo errores, cada uno con step y recovery sugerido
- [ ] No se expone ningún secret (API keys, webhook secrets)

## Relacionado

- Recibe escalaciones de `provision-orchestrator` (health check post-provisión)
- No delega a otros agentes — es la "última milla" operativa
