Distribución de builds VeriX
- Builds de VeriX
- Distribución de builds Android con EAS — VeriX
- Distribución de builds iOS con EAS — VeriX
- VeriX iOS Build & Apple Developer Integration
- Submit a TestFlight — VeriX (iOS)
Builds de VeriX
Builds de VeriX (scripts\build.ps1)
Cómo generar un build de VeriX con versión y nombre de archivo automáticos, para dev, test o prod.
Qué hace este script
build.ps1 es un wrapper alrededor de eas build. Dispara el build en la nube de Expo (los servidores de Expo compilan, no tu máquina — es exactamente lo mismo que correr eas build -p android --profile test a mano), espera a que termine, y descarga el .apk/.aab ya renombrado. No reemplaza nada de tu flujo normal, solo lo automatiza.
eas build --localNO se usa aquí. Si en algún lado ves referencias a builds "locales" en commits viejos de este repo, ya no aplica — el flujo actual es 100% en la nube.
Uso
Desde la raíz del repo (nexus33-app-verix), en PowerShell:
.\scripts\build.ps1 -Env test
.\scripts\build.ps1 -Env dev
.\scripts\build.ps1 -Env prod
Por defecto compila Android. Para iOS:
.\scripts\build.ps1 -Env test -Platform ios
El build en la nube tarda normalmente 15-20+ minutos — el script se queda esperando, no hace falta hacer nada mientras tanto.
Prerrequisitos
- Sesión iniciada en EAS:
npx eas-cli login(si nunca lo has hecho en esta máquina). - Conexión a internet (el build corre en los servidores de Expo, no localmente).
- Git instalado y este repo clonado con al menos un commit (el script usa el hash del commit actual).
No hace falta Android SDK, JDK, ni Xcode instalados — eso lo tiene Expo del lado de sus servidores.
Troubleshooting
An Expo user account is required to proceed / eas build exited with code 1
No hay sesión iniciada en EAS en esta máquina (el script corre con --non-interactive, así que no te va a pedir login solo — falla directo). Soluciónalo con:
npx eas-cli login
y confirma con npx eas-cli whoami. Después vuelve a correr el script normalmente. Ver también la nota sobre app.json más abajo si el build falló después de que la versión ya se bumpeó.
eas : term not recognized
Estás intentando correr eas directo en vez de npx eas-cli. El script usa npx eas-cli internamente, así que no necesitas tener eas-cli instalado global — pero si quieres el comando corto disponible en tu terminal: npm install -g eas-cli.
Qué hace el script, paso a paso
- Lee la versión actual de
app.json(expo.version). - Calcula la siguiente versión — ver "Versionado" abajo.
- Escribe la nueva versión en
app.json(en disco, sin commit/push — eso lo sigues haciendo tú manualmente, como siempre). - Obtiene el hash corto del commit actual (
git rev-parse --short HEAD). - Genera el timestamp del build.
- Mapea
-Enval perfil real deeas.json:dev→development,test→test,prod→production. - Corre
eas build -p <platform> --profile <perfil> --wait(equivalente a hacerlo a mano) y espera a que termine. - Cuando termina, toma el link de descarga que devuelve Expo y baja el archivo a
builds\<nombre-generado>.
Si algo falla en cualquier paso, el script se detiene y muestra el error — no deja archivos de build a medias con nombres incorrectos.
⚠️ Ojo con fallos después del paso 3. El bump de versión en
app.jsonocurre antes de disparar el build (paso 3 vs. paso 7). Si el build falla después de eso — por ejemplo, por no tener sesión iniciada en EAS —app.jsonqueda con la versión ya incrementada en disco, sin build real asociado. Antes de reintentar, revisagit diff app.json: puedes revertirlo (git checkout -- app.json) para no "quemar" un número de versión, o simplemente dejarlo y correr el script de nuevo (no pasa nada grave si el contador salta un número).
Formato del nombre de archivo
VeriX-{env}-{version}-{yyyyMMddHHmm}+{commitHash}.{apk|aab|ipa}
Ejemplo:
VeriX-test-1.0.1-202607241005+7bc21f0.apk
| Parte | Significado | Origen |
|---|---|---|
env |
dev, test o prod |
Parámetro -Env |
version |
Versión semántica | app.json (expo.version), auto-bumpeada por el script |
yyyyMMddHHmm |
Fecha/hora del build | Generado al momento de compilar |
commitHash |
Hash corto del commit actual | git rev-parse --short HEAD |
| Extensión | .apk, .aab, .ipa (o .tar.gz en builds de simulador iOS) |
Tomada del link real que devuelve Expo, no adivinada |
prod en Android genera .aab (Android App Bundle, lo que exige Google Play para publicar). dev/test generan .apk (instalable directo en un dispositivo). Esto ya estaba definido en eas.json, el script no lo cambia.
Versionado (app.json → expo.version)
Formato major.minor.patch:
major— siempre manual. Solo tú lo cambias, para indicar un cambio grande/breaking.minorypatch— semi-automáticos, con un contador global compartido entredev,testyprod(no es un conteo separado por ambiente):- Cada build (sin importar el ambiente) suma 1 al
patch. - Al llegar a 20 builds, el
patchvuelve a 0 y elminorsube en 1.
- Cada build (sin importar el ambiente) suma 1 al
| Build # | Versión |
|---|---|
| 1 (manual, punto de partida) | 1.0.0 |
| 2 | 1.0.1 |
| ... | ... |
| 20 | 1.0.19 |
| 21 (rollover) | 1.1.0 |
versionCode (Android) / buildNumber (iOS) — campos aparte
Estos no son lo mismo que expo.version de arriba. Son 2 campos separados (uno por plataforma) que las tiendas usan para exigir que cada build subido sea estrictamente más nuevo que el anterior:
android.versionCode(entero: 1, 2, 3...)ios.buildNumber(string: "1", "2", "3"...)
Hoy están configurados para auto-incrementarse solo en el perfil production (eas.json → "autoIncrement": true). Cada build de production los sube en 1 automáticamente — EAS los escribe en app.json solo, sin que el script tenga que hacer nada. test/development no los tocan (no lo necesitan: no se suben a las tiendas, y reinstalar un .apk con el mismo versionCode sobre uno viejo funciona bien en Android).
Salida
Los builds quedan en nexus33-app-verix\builds\ (carpeta ignorada por git, ver .gitignore — no se commitean).
Commit del bump de versión
El script deja app.json modificado en disco pero no commitea ni pushea nada. Cuando quieras dejar ese cambio de versión en git, hazlo tú manualmente como siempre (git add app.json, git commit, git push).
Pendiente / no cubierto todavía por este flujo
eas submit— subir el.aab/.ipaa Play Store / App Store todavía no está automatizado (eas.json→submit.productionestá vacío). Hoy la subida a las tiendas se hace manual con el archivo que este script genera. Los pasos completos para instalar/distribuir cada build (pruebas y producción) están documentados aparte: verdistribucion-android-eas.mdydistribucion-ios-eas.md.- Credenciales de firma (keystore Android / certificados iOS) — no verificadas todavía. EAS las pide de forma interactiva la primera vez que corras
eas build --profile production; no requiere trabajo previo, solo tenerlo en cuenta la primera vez. - Fichas de la app en Play Console / App Store Connect — no es código, hay que crearlas manualmente (screenshots, descripción, política de privacidad, data safety / privacy nutrition label) antes de poder subir el primer build.
- OTA updates (
expo-updates) — decisión consciente de dejarlo pendiente (2026-07-23). Para el primer lanzamiento no aporta lo suficiente frente a la complejidad que agrega, y al ser una app de cumplimiento regulatorio (DOT) hay valor en que cada cambio pase por el review formal de la tienda. Revisar de nuevo en 1-2 meses con datos reales de cadencia de updates/hotfixes. No requiere ningún cambio previo — es 100% aditivo cuando se decida hacerlo.
Distribución de builds Android con EAS — VeriX
A diferencia de iOS, Android no requiere registrar dispositivos ni certificados de por vida — un APK se puede instalar en cualquier teléfono con "orígenes desconocidos" habilitado. Esto hace que el flujo de pruebas sea más simple.
Para generar el build en sí (
.apk/.aab) con versión y nombre automáticos, verBUILD.md(scripts\build.ps1). Esta guía asume que ya tienes ese archivo listo.
Opción A: Test / instalación directa (APK)
Ideal para pruebas rápidas en cualquier dispositivo del equipo, sin pasar por Google Play.
1. Verificar el perfil en eas.json
Para pruebas, el perfil test debe generar un APK (instalable directo), no un AAB (que es exclusivo para Play Store):
"test": {
"distribution": "internal",
"android": {
"buildType": "apk"
}
}
2. Correr el build
.\scripts\build.ps1 -Env test -Platform android
El resultado es un .apk en la carpeta builds\.
3. Instalar en el dispositivo
Dos formas:
a) Link directo (más fácil para compartir)
- El build queda disponible en expo.dev con un link de descarga.
- Abre ese link desde el navegador del teléfono Android y descarga el APK.
- Si es la primera vez, Android pedirá habilitar "Instalar apps desconocidas" para ese navegador — se acepta una sola vez.
b) Cable USB (si tienes el .apk en la PC)
adb install builds\VeriX-test-<version>.apk
(requiere adb — viene con Android Studio / platform-tools, y el dispositivo con depuración USB activada)
Notas
- No hay expiración de certificado ni límite de dispositivos, a diferencia de iOS ad hoc.
- Cada instalación reemplaza la anterior si usas el mismo
applicationId— no necesitas desinstalar manualmente entre builds.
Opción B: Producción (publicación en Google Play)
1. Requisitos previos
- Cuenta de Google Play Console (pago único de $25, una sola vez).
- App creada en Play Console con su ficha (descripción, screenshots, política de privacidad, clasificación de contenido).
- Una cuenta de servicio (service account) de Google Cloud con permisos en Play Console, y su archivo JSON de credenciales — necesario para que
eas submitpueda subir builds automáticamente.- Se configura una vez en
eas.json→submit.production.android.serviceAccountKeyPath, apuntando al archivo.json(no se sube a git — agregarlo a.gitignore).
- Se configura una vez en
2. Ajustar el perfil de producción en eas.json
Play Store requiere formato AAB (Android App Bundle), no APK:
"production": {
"distribution": "store",
"android": {
"buildType": "app-bundle"
}
}
3. Generar el build
.\scripts\build.ps1 -Env prod -Platform android
4. Subir el build a Play Console
npx eas-cli submit -p android --latest
Esto sube el .aab automáticamente al track que definas (por defecto, internal — se puede cambiar a alpha, beta o production en eas.json bajo submit.production.android.track).
5. Testing interno en Play Console (recomendado antes de producción)
- En Play Console → tu app → Testing → Internal testing.
- Agrega testers por email o crea un link de opt-in.
- Los testers instalan la app desde el Play Store (no requiere APK manual) una vez aceptan la invitación.
- Esto evita mandar builds directo a producción sin pasar por revisión previa de tu equipo.
6. Promover a producción
- Una vez validado en internal testing, en Play Console → Production → Create new release → selecciona el build ya subido (o promuévelo directo desde el track de testing con "Promote release").
- Completa el rollout (puede ser gradual, ej. 20% → 50% → 100%, para reducir riesgo).
- Google revisa el release (usualmente horas, a veces hasta un par de días en la primera publicación de una app nueva).
Notas
- El
versionCodede Android debe ser mayor en cada release nuevo — si usas"autoIncrement": trueeneas.json(como ya está configurado en VeriX), EAS lo maneja automáticamente. - No puedes volver a subir el mismo
versionCodeuna vez publicado, ni siquiera si cancelas el rollout.
¿Cuál usar?
| Test (APK directo) | Producción (Play Store) | |
|---|---|---|
| Setup inicial | Ninguno | Cuenta de Play Console + service account |
| Requiere registrar dispositivo | No | No |
| Formato de build | APK | AAB |
| Pasa por revisión de Google | No | Sí (horas a días) |
| Ideal para | Prueba rápida en cualquier Android | Lanzamiento público / testers vía Play Store |
Comparación rápida con iOS
| Android | iOS | |
|---|---|---|
| Pruebas rápidas | APK directo, sin registrar nada | Requiere registrar UDID (ad hoc) |
| Testing con más gente | Internal testing track (Play Store) | TestFlight |
| Producción | Play Console (AAB) | App Store Connect (revisión completa) |
| Costo de cuenta developer | $25 único | $99/año |
Distribución de builds iOS con EAS — VeriX
Dos formas de instalar un build de prueba en un iPhone físico sin pasar por el simulador.
Para generar el build en sí (
.ipa/.tar.gz) con versión y nombre automáticos, verBUILD.md(scripts\build.ps1). Esta guía asume que ya tienes ese archivo listo.
Opción A: Ad Hoc (directo al dispositivo, sin TestFlight)
Rápido, pero limitado a dispositivos registrados manualmente (máx. 100 UDIDs/año en tu cuenta Apple Developer).
1. Ajustar el perfil en eas.json
"test": {
"distribution": "internal",
"ios": {
"simulator": false
}
}
2. Registrar el iPhone (obtener su UDID)
npx eas-cli device:create
- Genera un link/QR.
- Ábrelo desde Safari en el iPhone.
- Instala el perfil de configuración que se descarga — esto registra el UDID automáticamente en Expo/Apple.
3. Correr el build
.\scripts\build.ps1 -Env test -Platform ios
- EAS genera (o reutiliza) el certificado de distribución y un provisioning profile ad hoc que incluye ese dispositivo.
- El resultado es un
.ipa(no.tar.gz).
4. Instalar en el iPhone
- El build aparece en expo.dev o en el link que EAS imprime en consola al terminar.
- Abre ese link desde el navegador del iPhone.
- Toca instalar — no requiere Mac, App Store ni TestFlight.
Notas
- Solo dispositivos registrados antes de generar el provisioning profile pueden instalar el build.
- Si el dispositivo se agregó después de un build viejo, puede que necesites regenerar el profile:
eas build --clear-provisioning-profile - El provisioning profile expira (normalmente ~1 año).
Opción B: TestFlight
Mejor para testers externos o cuando no quieres registrar UDIDs uno por uno. Pasa por App Store Connect, así que toma un poco más de tiempo (revisión automática, no manual, suele ser minutos-horas).
Guía detallada y ya probada de este flujo completo (incluyendo el método de autenticación que sí funciona en esta cuenta): ver
testflight-submit-verix.md. Los pasos abajo son el resumen genérico — esa guía tiene el detalle exacto paso a paso con el que ya se validó un submit real.
1. Requisitos previos
- Cuenta de Apple Developer Program (paga, $99/año) vinculada al proyecto en EAS.
- App creada en App Store Connect.
2. Ajustar el perfil de build en eas.json
Para TestFlight normalmente se usa el perfil de production (o uno dedicado), con distribución store:
"production": {
"distribution": "store",
"ios": {
"simulator": false
}
}
3. Generar el build
.\scripts\build.ps1 -Env prod -Platform ios
(o el ambiente que corresponda al perfil que uses para TestFlight)
4. Subir el build a App Store Connect
npx eas-cli submit -p ios --latest
- Sube el
.ipamás reciente automáticamente a App Store Connect. - Espera a que Apple procese el build (aparece en la sección TestFlight de App Store Connect, usualmente en minutos).
5. Agregar testers
- En App Store Connect → tu app → pestaña TestFlight.
- Agrega testers por email (grupo interno) o crea un link público de invitación si quieres que cualquiera con el link pueda unirse.
- Los testers instalan la app TestFlight desde el App Store, y desde ahí instalan tu build usando el link/invitación.
Notas
- No requiere registrar UDIDs — cualquier tester invitado puede instalar sin configuración previa.
- Los builds de TestFlight expiran a los 90 días.
- Testers externos (fuera de tu equipo de Apple Developer) requieren que Apple apruebe el build para "external testing" (revisión ligera, normalmente rápida).
Opción C: Producción (publicación en App Store)
El build es técnicamente el mismo que para TestFlight (distribution: "store"), pero además de subirlo hay que enviarlo a revisión de Apple y publicarlo.
1. Build y submit (igual que TestFlight, pasos 3-4)
.\scripts\build.ps1 -Env prod -Platform ios
npx eas-cli submit -p ios --latest
Esto sube el .ipa a App Store Connect — mismo build que usarías para TestFlight, solo que ahora lo vas a enviar a revisión en vez de (o además de) dejarlo en testing interno.
2. Completar la ficha en App Store Connect
Antes de enviar a revisión, en App Store Connect → tu app → App Store tab necesitas tener listo:
- Screenshots (por tamaño de dispositivo)
- Descripción, keywords, categoría
- Política de privacidad (URL)
- Clasificación de contenido (age rating)
- Precio/disponibilidad por país
3. Enviar a revisión
- Selecciona el build que subiste (paso 1) en la sección Build.
- Click en Add for Review → Submit for Review.
- Apple revisa (normalmente 24-48h, puede variar).
4. Publicación
- Si aprueban, puedes elegir publicación manual (tú decides cuándo sale al público) o automática (sale apenas Apple aprueba) — se configura antes de enviar a revisión.
- También puedes usar phased release (lanzamiento gradual a % de usuarios en 7 días) para reducir riesgo si algo sale mal.
Notas
- El número de versión (
app.json→version) y elbuildNumberdeben ser mayores a la última versión publicada — tu script ya incrementa el patch automáticamente, pero revisa que no choque con una versión ya en revisión. - Una vez enviado a revisión, no puedes subir un build nuevo sin cancelar el envío anterior.
- Si tu app usa capacidades especiales (push notifications, in-app purchases, etc.), Apple puede pedir información adicional o rechazar por incumplimiento de guidelines — vale la pena revisar el build en TestFlight primero antes de enviarlo a producción.
¿Cuál usar?
| Ad Hoc | TestFlight | Producción | |
|---|---|---|---|
| Setup inicial | Rápido | Más pasos (App Store Connect) | Igual que TestFlight + ficha completa |
| Requiere registrar UDID | Sí | No | No |
| Límite de dispositivos | 100/año | Sin límite práctico | Sin límite (público) |
| Expiración del build | ~1 año | 90 días | No expira (versión publicada) |
| Pasa por revisión de Apple | No | Ligera (external testing) | Sí (revisión completa, 24-48h) |
| Ideal para | Prueba rápida en 1-2 dispositivos del equipo | Testers externos, distribución más amplia | Lanzamiento público |
VeriX iOS Build & Apple Developer Integration
This document outlines the step-by-step procedure for configuring, building, and deploying the VeriX iOS mobile application using Expo (EAS Build), Apple Developer Account, and TestFlight, following SOC 2 Least Privilege Access security principles.
📌 Executive & Technical Overview
- App Name: VeriX
- Bundle Identifier:
com.nexus33.verix - Build System: Expo Application Services (EAS Build & Submit)
- Target OS: iOS 14.0+
- Distribution Target: TestFlight (Internal & External Beta Testing)
- Security & Compliance: SOC 2 Type II compliant (Developer permissions strictly scoped; Account Holder handles Identifier registration).
🛠️ Section 1: eas.json Profile Configuration
The eas.json file is configured so that test builds target physical iOS devices via TestFlight using Apple Store distribution ("distribution": "store" and "simulator": false), while preserving Android APK generation.
{
"expo": {
"name": "VeriX",
"slug": "nexus33-app-verix",
"version": "1.0.9",
"orientation": "portrait",
"icon": "./assets/images/icon-ios.png",
"userInterfaceStyle": "dark",
"scheme": "verix",
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.nexus33.verix",
"buildNumber": "1",
"infoPlist": {
"ITSAppUsesNonExemptEncryption": false
}
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/android-icon-foreground.png",
"backgroundImage": "./assets/android-icon-background.png",
"monochromeImage": "./assets/android-icon-monochrome.png"
},
"package": "com.nexus33.verix",
"versionCode": 1,
"predictiveBackGestureEnabled": false
},
"web": {
"favicon": "./assets/images/verix_logo.png",
"bundler": "metro"
},
"plugins": [
"expo-router",
"expo-font",
"expo-secure-store",
"expo-status-bar",
"expo-sharing",
[
"expo-splash-screen",
{
"image": "./assets/images/verix_logo.png",
"resizeMode": "contain",
"backgroundColor": "#0D1B2A"
}
],
"expo-asset",
"@react-native-community/datetimepicker",
"expo-web-browser",
"expo-mail-composer",
[
"expo-local-authentication",
{
"faceIDPermission": "Allow VeriX to use Face ID for quick, secure sign-in."
}
],
[
"expo-image-picker",
{
"photosPermission": "VeriX needs access to your photo library to attach images to support requests and evaluation records.",
"cameraPermission": "VeriX needs access to your camera to take photos to attach to support requests and evaluation records.",
"microphonePermission": false
}
]
],
"experiments": {
"typedRoutes": true
},
"extra": {
"router": {},
"eas": {
"projectId": "b8155c89-b50f-40fd-b73b-18d9a9a59e6e"
},
"iosAppStoreId": ""
},
"owner": "devnexus33s-team"
}
}
🔐 Section 2: Apple Developer Portal Setup (SOC 2 Compliant)
To comply with SOC 2 Least Privilege Access Control, software developers are assigned restricted roles (Developer / Member) without requiring full Admin privileges on the Apple Developer Account.
Step 1: Pre-Registering the App ID (Account Holder / Admin Only)
The Account Holder (or designated Admin) performs a one-time registration of the App Bundle Identifier:
- Log into Apple Developer Portal.
- Navigate to Certificates, Identifiers & Profiles ➔ Identifiers.
- Click the
+(Add) button next to Identifiers. - Select App IDs ➔ Click Continue.
- Select Type: App ➔ Click Continue.
- Enter details:
- Description:
VeriX App - Bundle ID: Select Explicit and enter
com.nexus33.verix
- Description:
- Leave Capabilities as default (none required to be checked).
- Click Continue ➔ Click Register.
[!NOTE] Pre-registering the App ID allows developers with standard Developer roles to trigger EAS Builds without incurring HTTP 403 Forbidden permission errors.
🚀 Section 3: Initial Credentials & EAS Linking (One-Time Execution)
The first time an iOS build is triggered for com.nexus33.verix, EAS CLI requires an interactive login to validate and generate the iOS Distribution Certificate on Expo's secure servers.
Interactive Build Command:
npx eas-cli build -p ios --profile test
Interactive Console Flow:
- Select Team: Choose
Nexus 33 Group LLC (Z66MZ82MC2). - Apple ID Authentication: Enter the Apple ID email.
- Password / 2FA: Enter password and 6-digit Apple Two-Factor Verification Code.
- Credential Setup Prompt: Confirm
Yeswhen prompted "Do you want EAS to manage iOS credentials?".
EAS will detect the existing com.nexus33.verix App ID, generate the iOS Distribution Certificate, and store credentials securely on Expo Cloud.
⚙️ Section 4: Automated Build Execution (build.ps1)
Once initial credentials are created, subsequent iOS test builds can be executed automatically using the repository wrapper script:
.\scripts\build.ps1 -Env test -Platform ios
Automated Script Steps:
- Increments
app.jsonpatch version (1.0.X). - Reads current Git commit hash and timestamp.
- Initiates
eas build -p ios --profile test --non-interactive --json --wait. - Compiles the
.ipapackage on Expo Cloud servers. - Downloads the
.ipaartifact locally to the project root.
📲 Section 5: TestFlight Upload & Beta Testing
Once the .ipa build is completed (status: FINISHED), submit the build to TestFlight:
npx eas-cli submit -p ios --profile test
Post-Submission Steps:
- Log into App Store Connect.
- Go to Apps ➔ VeriX ➔ TestFlight tab.
- Once Apple finishes binary processing (~5-10 minutes), add Internal/External Testers.
- Testers receive an email / push notification to install VeriX directly on their iPhones via the TestFlight app.
🛡️ Troubleshooting & Security Guidelines
| Issue / Error | Root Cause | Resolution |
|---|---|---|
iOS simulator build (.tar.gz) generated instead of .ipa |
"simulator": true in eas.json |
Set "ios": { "simulator": false } under the target profile. |
Apple 403 Access Forbidden |
Developer account lacks Admin rights to create App ID | Follow Section 2 (Have Account Holder register com.nexus33.verix once). |
Distribution Certificate not validated for non-interactive builds |
Running --non-interactive before credentials exist |
Run npx eas-cli build -p ios --profile test interactively once (Section 3). |
Documentation prepared for Nexus 33 Group LLC — VeriX Development Team.
Submit a TestFlight — VeriX (iOS)
Guía completa, ya probada de punta a punta, para subir un build de VeriX a TestFlight y que un tester lo instale en su iPhone. Incluye el método de autenticación que sí funciona en esta cuenta de Apple Developer (Nexus 33 Group LLC) y por qué el método "estándar" (API Key) no sirve aquí.
Requiere tener ya un build de iOS generado. Ver
BUILD.mdpara eso (scripts\build.ps1 -Env test -Platform ios).
⚠️ Importante: usar Apple ID + App-Specific Password, NO API Key
La forma "recomendada" por Expo para eas submit es una API Key de App Store Connect (.p8 + Key ID + Issuer ID). En esta cuenta esa forma no funciona — probamos 5 variantes distintas (key manual, .bat con variables de entorno, generación automática por EAS, servicio de credenciales cifrado eas credentials, y una segunda key nueva generada desde cero) y las 5 fallaron con el mismo error:
Error: Apple 403 detected - Access forbidden.
This request is forbidden for security reasons - The API key in use does not allow this request
× Failed to fetch App Store Connect API Key.
Se descartaron como causa: rol de la key (era Admin), tipo de key (Team Keys, que es el correcto), Términos y Condiciones (aceptados), membresía de Apple Developer (activa y pagada), y corrupción del archivo .p8 (se confirmó que nunca se abrió/editó). El patrón (2 keys distintas, mismo error exacto) apunta a una restricción a nivel de cuenta que Apple no expone con un mensaje claro — posiblemente ligada a que la membresía de la organización se aprobó recientemente.
La solución que sí funcionó: autenticar con Apple ID + una App-Specific Password, en vez de una API Key. Es un mecanismo distinto dentro de eas-cli que no pasa por la llamada que estaba fallando.
Paso 1 — Generar una App-Specific Password
Esto se hace en la cuenta personal de Apple, no en App Store Connect (son sitios distintos).
- Ve a https://appleid.apple.com (no
appstoreconnect.apple.com). - Inicia sesión con el Apple ID que tiene acceso al equipo Nexus 33 Group LLC (ej.
hectoregarciap@hotmail.com). - Click en Sign-In and Security.
- Busca la tarjeta App-Specific Passwords → click en ella.
- Click en + para generar una nueva.
- Ponle un nombre descriptivo, ej.
EAS Submit. - Apple muestra la contraseña en formato
abcd-efgh-ijkl-mnop. Cópiala en ese momento — Apple no la vuelve a mostrar después.
Cada dev del equipo que vaya a hacer
eas submitnecesita generar la suya propia con su propio Apple ID (si tiene acceso al equipo).
Paso 2 — Configurar eas.json
Agrega el appleId (esto no es secreto, se puede dejar en el repo) dentro del perfil de submit que uses:
"submit": {
"test": {
"ios": {
"appleId": "hectoregarciap@hotmail.com"
}
}
}
Paso 3 — Setear la contraseña como variable de entorno (por sesión, no se guarda en ningún archivo)
En PowerShell, antes de correr el submit:
$env:EXPO_APPLE_APP_SPECIFIC_PASSWORD = "abcd-efgh-ijkl-mnop"
No hay confirmación visual — es normal. Esta variable solo vive en esa ventana de terminal; se pierde al cerrarla (por diseño, para no dejarla en disco).
Para no repetir esto cada sesión (opcional, persiste solo en tu máquina, nunca en el repo):
[System.Environment]::SetEnvironmentVariable("EXPO_APPLE_APP_SPECIFIC_PASSWORD", "abcd-efgh-ijkl-mnop", "User")
(abre una terminal nueva para que tome efecto)
Paso 4 — Correr el submit
En la misma terminal donde seteaste la variable:
npx eas-cli submit -p ios --profile test
Selecciona el build que quieres subir cuando te pregunte. Con la contraseña específica ya en el entorno, no debería pedirte ninguna API Key — autentica directo con el Apple ID.
Al terminar deberías ver:
√ Submitted your app to Apple App Store Connect!
Your binary has been successfully uploaded to App Store Connect!
Apple tarda 5-10 minutos en procesar el build (a veces más). Llega un correo cuando termina.
Paso 5 — Agregar testers en App Store Connect
- Ve a https://appstoreconnect.apple.com → selecciona la app VerixApp.
- Pestaña TestFlight → sección iOS Builds.
- Una vez el build aparece con estado "Ready to Submit" o "Ready to Test", entra al build (click en el número/ícono).
- Si pide Export Compliance (uso de encriptación), respóndelo según corresponda a la app (la mayoría de apps que solo usan HTTPS estándar responden que no usan encriptación propia / usan solo la exenta).
- Vuelve a TestFlight → Internal Testing → el grupo ya existente (ej. "Team (Expo)", creado automáticamente por Expo).
- Click en el grupo → pestaña Testers → + para agregar un email.
Requisito: para poder agregar a alguien como tester interno, esa persona debe existir primero como usuario del equipo en Users and Access → People. Si su email no aparece, hay que invitarla ahí primero.
Paso 6 — El tester instala VeriX
Desde el iPhone de la persona invitada:
- Revisa el correo — llega una invitación de Apple/TestFlight con el nombre de la app y un código de 8 caracteres (ej.
BHHDZRWF). - Instala la app TestFlight desde el App Store, si no la tiene.
- Abre TestFlight → toca Redeem.
- Escribe el código del correo.
- VeriX aparece en la lista → toca Install.
El código de canje es único por invitación/persona — cada tester tiene el suyo, no se puede compartir entre dos personas.
Resumen rápido (una vez ya configurado todo)
# 1. Generar build (ver BUILD.md)
.\scripts\build.ps1 -Env test -Platform ios
# 2. Setear la contraseña (si no está persistida ya)
$env:EXPO_APPLE_APP_SPECIFIC_PASSWORD = "abcd-efgh-ijkl-mnop"
# 3. Submit
npx eas-cli submit -p ios --profile test
# 4. Esperar correo de Apple (~5-10 min)
# 5. Agregar tester en App Store Connect (si es alguien nuevo)
# 6. El tester canjea el código en TestFlight desde su iPhone
Ver también
BUILD.md— cómo generar el build (.ipa) con versión y nombre automáticos.distribucion-ios-eas.md— alternativa de distribución ad hoc (sin pasar por TestFlight, instalación directa en dispositivos registrados).distribucion-android-eas.md— equivalente para Android.