Rotates the active Stripe account of a SpecBox project safely. Wraps the switch_stripe_account MCP tool with a UX layer: shows current alias store, asks for from/to, runs dry-run, formats the plan in Markdown, asks for literal confirmation, executes, and surfaces the rollback runbook if something fails. Supports both account_mode='standard' (SaaS, e-commerce) and 'connect' (marketplace). Use when the user says "switch stripe account", "rotar cuenta stripe", "cambiar cuenta stripe", "cambiar d...
Scanned 6/1/2026
Install via CLI
openskills install EmbedBuild/specbox-engine---
name: stripe-switch-account
description: >
Rotates the active Stripe account of a SpecBox project safely. Wraps the
switch_stripe_account MCP tool with a UX layer: shows current alias store,
asks for from/to, runs dry-run, formats the plan in Markdown, asks for
literal confirmation, executes, and surfaces the rollback runbook if
something fails. Supports both account_mode='standard' (SaaS, e-commerce)
and 'connect' (marketplace). Use when the user says "switch stripe
account", "rotar cuenta stripe", "cambiar cuenta stripe", "cambiar de cuenta
de stripe", "rotate stripe account", "stripe credentials rotation".
context: direct
allowed-tools: Read, Grep, Glob, Bash(*), Write, Edit, mcp__specbox-stripe__*, mcp__specbox-supabase__*
---
# /stripe-switch-account — Stripe credentials rotation skill
Companion of `/stripe-connect` and `/stripe-standard`. Where those scaffold a
brand-new integration, this one rotates an already-deployed integration to a
**different Stripe account**. Common cases:
- Test → live (going to production for the first time)
- Live → live (changing legal entity, splitting from a former partner)
- Live → test (rolling back to a sandbox after an incident)
The skill never moves money, customers or subscriptions across accounts —
those are immutable once created. What it rotates is the **infrastructure**:
which account the platform's Edge Functions talk to, where the webhooks
fire, which `sk_*` lives in Supabase secrets.
## Uso
```
/stripe-switch-account
```
Sin argumentos. La skill detecta el alias store, pregunta from/to, propone un
plan, pide confirmación literal y ejecuta.
## Pre-requisitos
1. **Alias store** con al menos 2 entradas. Crear con:
```
mcp__specbox-stripe__store_stripe_alias_tool({
alias_name: "prod",
stripe_api_key: "sk_live_...",
project_path: "/abs/path/to/project"
})
```
La store vive cifrada en `.claude/secrets/stripe_aliases.enc.json`.
2. **specbox-stripe-mcp v0.3+** registrado en `.claude/settings.local.json`.
3. **(Recomendado)** `specbox-supabase-mcp` registrado para auto-rotación de
Edge Function secrets. Si falta, la skill genera `doc/PENDING_SWITCH_SECRETS.md`
y guía al usuario para hacerlo manualmente.
---
## Paso 0 — Preflight
### 0.1 Validar proyecto SpecBox
```bash
test -f .claude/settings.local.json || test -f .claude/settings.json || {
echo "ERROR: No es un proyecto SpecBox. Ejecuta onboard_project primero."
exit 1
}
```
### 0.2 Detectar `specbox-stripe-mcp`
Comprobar que el MCP está registrado: `grep -q specbox-stripe .claude/settings.local.json`.
Si falta → abortar con instrucciones de instalación:
```
ERROR: specbox-stripe-mcp no está registrado en este proyecto.
Añádelo a .claude/settings.local.json bajo "mcpServers".
Mínimo requerido: v0.3.0 (incluye switch_stripe_account).
```
### 0.3 Detectar el modo del proyecto
Leer `package.json` / `pubspec.yaml` / Edge Functions existentes:
- ¿Hay `supabase/functions/stripe-webhook` con un solo endpoint? → `account_mode='standard'`.
- ¿Hay 2 webhooks (platform + connect) o referencias a `application_fee_percent`? → `account_mode='connect'`.
Si la heurística es ambigua, preguntar al usuario.
### 0.4 Listar aliases disponibles
```
mcp__specbox-stripe__list_stripe_aliases_tool_mcp({ project_path: "{abs}" })
```
Si hay menos de 2 → abortar:
```
ERROR: Necesitas al menos 2 aliases (origen + destino).
Tienes registrados: [lista]
Crea otro con store_stripe_alias_tool antes de switch.
```
---
## Paso 1 — UX inicial
Mostrar al usuario:
```
🔄 Stripe Switch Account
Aliases registrados en este proyecto:
• prod (live, last used 2026-04-29 14:22)
• staging (test, last used 2026-04-15 10:01)
• legacy (live, never used)
¿De qué alias migras? (from): prod
¿A qué alias migras? (to): staging
¿Modo de cuenta? standard
¿Qué hacer con la cuenta de origen tras el switch?
(1) keep_old_active — no tocar nada (DEFAULT, recomendado para rollback rápido)
(2) archive_products_only — archivar los products SpecBox, dejar webhooks
(3) deactivate_webhooks_only — deshabilitar webhooks, dejar products
(4) full_archive — todo lo anterior + cancelar subs SpecBox-managed (irreversible)
Elección: 1
```
Validar before continuar:
- `from != to`
- `from` y `to` existen en alias_store
- En `connect` → preguntar también `connect_events`/`connect_url` si difieren
---
## Paso 2 — Dry-run obligatorio
```
mcp__specbox-stripe__switch_stripe_account_tool({
from_alias: "prod",
to_alias: "staging",
account_mode: "standard",
project_path: "{abs}",
platform_url: "https://{ref}.supabase.co/functions/v1/stripe-webhook",
platform_events: [...read from project's events.yaml or defaults...],
scope_action: "keep_old_active",
dry_run: true
})
```
Formatear la respuesta como Markdown:
```
📋 Plan de migración (dry-run)
ORIGEN (prod, sk_live_***)
Webhook endpoints: 1 SpecBox-managed
Products: 3
Subscriptions activas: 27
Customers: 142
DESTINO (staging, sk_test_***)
Webhook endpoints: 0
Products: 0
ACCIONES PROPUESTAS
1. Crear 1 webhook endpoint en destino (events: ...)
2. Replicar catálogo (3 products + sus prices) ← solo si pasaste catalog
3. Inyectar secrets en Supabase (3 keys) ← si specbox-supabase MCP detectado
↳ si no: doc/PENDING_SWITCH_SECRETS.md
4. scope_action sobre origen: keep_old_active (no toca nada)
Duración estimada: ~12 segundos
⚠️ IMPORTANTE: Las subscripciones, customers, y métodos de pago de la
cuenta origen NO se mueven. Siguen vivos en prod. Si alguien tenía
sesión iniciada y va a renovar, el cobro irá a prod, NO a staging.
Este flow es para infrastructure rotation, no migración de business data.
```
---
## Paso 3 — Confirmación literal
```
Para ejecutar este switch, escribe EXACTAMENTE:
Yes, switch from prod to staging
(con esos espacios y mayúsculas; un fallo de typing aborta el switch)
```
Si el usuario escribe cualquier otra cosa → abortar sin tocar nada.
Si `scope_action='full_archive'` → segunda confirmación con
`confirm_token="I understand this archives all SpecBox resources in the source account"`.
---
## Paso 4 — Ejecutar real
```
mcp__specbox-stripe__switch_stripe_account_tool({
...mismo payload que dry-run...
dry_run: false
})
```
Streaming progress al usuario:
```
✓ Pre-flight OK
✓ Webhook endpoint creado en destino: we_1TabcXyz
✓ 3/3 products replicados en destino
✓ Secrets inyectados en Supabase (3 nombres: STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PUBLISHABLE_KEY)
✓ scope_action keep_old_active: cuenta origen intacta
✅ Switch completado en 11.2s.
```
Si algún paso falla:
```
✗ Webhook endpoint creado en destino
✗ Products replicación: FAILED (E_LIMIT_REACHED)
🔄 Iniciando rollback automático...
✓ Webhook destino eliminado
⚠ Rollback completo. Sistema de vuelta al estado pre-switch.
Revisa los logs y vuelve a intentar.
```
Si rollback también falla:
```
🚨 Rollback parcialmente fallido. Estado del sistema mixto.
Runbook generado en: doc/SWITCH_FAILURE_RUNBOOK.md
Sigue las instrucciones manualmente.
```
---
## Paso 5 — Smoke-test post-switch
Sugerir al usuario:
```
Próximos pasos:
1. Reload de Edge Functions (Supabase los recoge automáticamente).
2. stripe listen --forward-to {platform_url} (con la NUEVA cuenta)
3. Test de un signup nuevo:
- Card 4242 4242 4242 4242
- Verifica que aparece en https://dashboard.stripe.com/{test|live}/customers de la cuenta DESTINO.
4. Si todo OK y scope_action era 'keep_old_active' → considera ejecutar
/stripe-switch-account de nuevo con scope_action='archive_products_only'
una vez confirmes que no necesitas rollback.
```
Si el usuario responde "rollback please":
```
/stripe-switch-account
from: staging
to: prod
```
Es exactamente el mismo flow al revés (siempre que `prod` aún esté `keep_old_active`).
---
## Anexo A — Errores comunes
| Error | Causa | Fix |
|-------|-------|-----|
| `E_ALIAS_NOT_FOUND` | El alias no está en la store | Crear con `store_stripe_alias_tool` |
| `E_DECRYPT_FAILED` | macOS Keychain inaccesible o passphrase distinto | Re-ingresar passphrase / re-crear keychain entry |
| `E_INVALID_KEY` (en alias) | sk_test_/sk_live_ malformado | Pegar de nuevo desde el dashboard |
| `E_LIVE_MODE_NOT_ALLOWED` | sk_live_* sin opt-in | Pasar `allow_live_mode=true` + `live_mode_confirm_token="I acknowledge this affects real money"` |
| `E_LIMIT_REACHED` | >16 webhook endpoints en la cuenta destino | Borrar los huérfanos: `stripe webhooks list --limit=100` y purga manual |
| `E_SUPABASE_WRITE_FAILED` | PAT expirado / project_ref incorrecto | Revisar `SUPABASE_ACCESS_TOKEN` |
| `E_CONFIRMATION_REQUIRED` | Token literal incorrecto | Copiar el token exactamente como aparece en el mensaje de error |
---
## Anexo B — `.gitignore` enforcement
La store cifrada en `.claude/secrets/stripe_aliases.enc.json` se añade a
`.gitignore` automáticamente la primera vez que se llama a
`store_stripe_alias_tool`. La skill lo verifica antes de cualquier acción.
Si por alguna razón está commiteada al repo, **revoca todas las keys de
Stripe inmediatamente y rota** — el archivo cifrado no debería bastar para
recuperarlas, pero asume compromiso.
---
## Referencias
- Tool docs: `mcp__specbox-stripe__switch_stripe_account_tool`
- Alias store: `packages/specbox-stripe-mcp/src/specbox_stripe_mcp/lib/alias_store.py`
- Skills hermanas: `/stripe-connect` (marketplace), `/stripe-standard` (no-Connect)
- Tracking: SpecBox board `ff-bc73b5d69f91`, US-STRIPE-SWITCH-ACCOUNT
No comments yet. Be the first to comment!