# Kasy App

App Flutter con backend Firebase — generado por kasy.

---

## Documentación

La documentación completa de Kasy está en **[kasy.dev/docs](https://kasy.dev/docs)** — instalación, features, personalización, publicación y troubleshooting, paso a paso.

Este proyecto también incluye guías locales (funcionan offline):

| Guía | Contenido |
|------|-----------|
| [docs/auth-setup.md](docs/auth-setup.md) | Activar login con Google, Apple y Facebook |
| [docs/revenuecat-setup.md](docs/revenuecat-setup.md) | Activar suscripciones (RevenueCat) del test a producción |
| [docs/ad_mobs.md](docs/ad_mobs.md) | Anuncios (AdMob) y recompensas verificadas |
| [docs/ios-release.md](docs/ios-release.md) | Publicar en iOS con Mac (`kasy ios`) |
| [docs/codemagic-release.md](docs/codemagic-release.md) | Publicar sin Mac (`kasy codemagic`) |
| [docs/figma-workflow.md](docs/figma-workflow.md) | Flujo Figma → Flutter para asistentes de IA |
| [docs/figma-guia.md](docs/figma-guia.md) | Guía Figma paso a paso (rebrand y pantallas) |
| [design/README.md](design/README.md) | Design system Figma (enlace Community + duplicate) |

---

## Cómo empezar

```sh
kasy run             # recomendado — lee el .env y elige las claves correctas
kasy run --ios       # simulador iOS
kasy run --android   # emulador Android
kasy run --web       # web en localhost:5555
```

Alternativas: `make run` o `flutter run` también funcionan, pero sin los extras de `kasy run` (selección automática de clave RevenueCat, log en `.kasy/run.log`, aviso de update).

**Dispositivo físico por cable**
- iOS: conecta el iPhone → confía en este ordenador → Xcode → Window → Devices → emparejar
- Android: Configuración → Opciones de desarrollador → activar depuración USB

**Deploy del backend** (cuando estés listo):

```sh
kasy deploy
```

---

## Claves y credenciales

Este proyecto usa dos tipos de credenciales. Entender la diferencia evita confusión al configurar.

### Claves del app (quedan en el proyecto)

Están en el archivo **`.env`** en la raíz del proyecto (cada clave tiene un comentario explicativo). `kasy run` lee el `.env` e inyecta los valores en el build vía `--dart-define`; Flutter los lee con `String.fromEnvironment()`. **Nunca van al servidor.**

| Variable | Módulo | Cómo obtener |
|----------|--------|--------------|
| `RC_TEST_KEY` | RevenueCat | Panel RevenueCat → Apps → Test Store → clave (`test_…`). **Una sola clave sirve para iOS+Android.** Usada automáticamente en simulador/emulador. |
| `RC_IOS_PROD_KEY` | RevenueCat | Panel RevenueCat → Apps → App Store → clave (`appl_…`). Usada automáticamente en iPhone físico (Sandbox y Producción). |
| `RC_ANDROID_PROD_KEY` | RevenueCat | Panel RevenueCat → Apps → Google Play → clave (`goog_…`). Usada automáticamente en Android físico. |
| `RC_WEB_API_KEY` | RevenueCat Web | Panel RevenueCat → Apps → Web Billing → clave **producción** (`rcb_…`, no `rcb_sb_`) en builds release |
| `SENTRY_DSN` | Sentry | Panel Sentry → Proyecto → DSN |
| `MIXPANEL_TOKEN` | Mixpanel | Panel Mixpanel → Configuración → Token |

Para actualizar una clave, edita el `.env` y vuelve a correr `kasy run`.

### RevenueCat: `kasy run` elige la clave automáticamente

La CLI detecta si vas a correr en **simulador/emulador** o en **dispositivo físico** e inyecta la clave correcta:

| Dónde corres | Clave usada |
|---|---|
| iOS Simulator / Android Emulator | `RC_TEST_KEY` (test_) |
| iPhone físico | `RC_IOS_PROD_KEY` (appl_) — fallback `RC_TEST_KEY` si falta |
| Android físico | `RC_ANDROID_PROD_KEY` (goog_) — fallback `RC_TEST_KEY` si falta |

Forzar manualmente: `kasy run --rc=test` o `kasy run --rc=prod`. `--rc=auto` (por defecto) aplica la regla anterior.

- **¿Por qué el split?** Los simuladores no pueden hacer compras reales con claves `appl_`/`goog_` — solo funciona Test Store de RevenueCat. En dispositivo físico, `appl_`/`goog_` cubre Sandbox y Producción (el SDK lo detecta).
- **TestFlight y release:** usa las claves de producción. **NUNCA subas `test_` a la tienda** — el SDK de RevenueCat crashea el app en release.
- **VS Code (F5 sin kasy run):** `launch.json` usa `RC_TEST_KEY` por defecto (o producción si test_ falta). Para alternar manualmente, corre `kasy run`.

---

### Secrets del servidor (quedan en Secret Manager de GCP)

Usados por las **Cloud Functions** en tiempo de ejecución. **Nunca en el código del app.**

| Secret | Usado por | Cómo obtener |
|--------|-----------|--------------|
| `REVENUECAT_WEBHOOK_KEY` | Webhook de suscripciones | Dashboard RevenueCat → Webhooks → Authorization header |
| `META_ACCESS_TOKEN` | Meta Conversions API | Meta Business Manager → System Users → Token |
| `META_DATASET_ID` | Meta Conversions API | Meta Business Manager → Events Manager → Dataset ID |

Para configurar o actualizar cada secret:

```sh
firebase functions:secrets:set REVENUECAT_WEBHOOK_KEY --project=YOUR_PROJECT_ID
firebase functions:secrets:set META_ACCESS_TOKEN --project=YOUR_PROJECT_ID
firebase functions:secrets:set META_DATASET_ID --project=YOUR_PROJECT_ID
```

> Cada comando pide el valor de forma interactiva. El valor **no aparece** en la terminal.

Para ver los secrets existentes:

```sh
gcloud secrets list --project=YOUR_PROJECT_ID
```

---

## Internacionalización (i18n)

El app soporta **3 idiomas**: inglés (`en`), portugués (`pt`) y español (`es`).

### Cómo se elige el idioma

```
App abre
  ├─ ¿Tiene idioma guardado por el usuario? → usa el guardado
  └─ No → lee el idioma del dispositivo/navegador
            ├─ ¿Es en, pt o es? → usa ese idioma
            └─ No es ninguno → usa el idioma por defecto (base_locale)
```

### Cambiar idioma por defecto (fallback)

Cuando el dispositivo del usuario está en un idioma no soportado (ej: japonés, francés), el app usa el **idioma por defecto**. Por defecto es inglés. Para cambiar a portugués:

**`slang.yaml`**
```yaml
base_locale: pt   # cambiar aquí: en | pt | es
```

Luego ejecuta:
```sh
dart run slang
```

### Añadir o editar traducciones

Los archivos están en `lib/i18n/`:
- `en.i18n.json` — inglés
- `pt.i18n.json` — portugués
- `es.i18n.json` — español

Tras editar cualquier `.i18n.json`, siempre ejecuta `dart run slang` para regenerar `translations.g.dart`.

### Selector de idioma

El usuario puede cambiar el idioma en **Configuración → Idioma**. La elección se guarda en el dispositivo y se restaura en la próxima apertura del app.

---

## Webhook RevenueCat

El webhook recibe eventos de compra (nueva suscripción, renovación, cancelación) de RevenueCat.

**En el dashboard de RevenueCat:** Webhooks → añadir URL de la función → Authorization header = valor de `REVENUECAT_WEBHOOK_KEY`.

---

## Deploy

```sh
# Deploy completo (Functions + reglas Firestore + reglas Storage)
firebase deploy --only functions,firestore:rules,storage --project=YOUR_PROJECT_ID

# Solo Functions
firebase deploy --only functions --project=YOUR_PROJECT_ID
```

---

## Publicar en iOS (App Store)

Guía completa: [docs/ios-release.md](docs/ios-release.md)

```bash
kasy ios configure   # una vez — credenciales Apple
kasy ios release     # genera IPA y sube a App Store Connect
```

Sin Mac: [docs/codemagic-release.md](docs/codemagic-release.md)

---

## Seguridad

El `.gitignore` ya excluye: `firebase_key.json`, `.env`, `.env.*`, `*.pem`, `*.keystore`, `.kasy/apple.env`, `.kasy/codemagic.env`, `.kasy/*.log`.

Nunca subas credenciales al repositorio.
