From 6c28bbd576dfc89847b950945d58a8eae2a68b1c Mon Sep 17 00:00:00 2001 From: Justin Hernandez Date: Tue, 11 Nov 2025 15:53:38 -0800 Subject: [PATCH] Update agents.md files to protect against out of memory tests (#1395) * memory and test reminders * clean up migration docs * format --- .cursor/rules/mobile-sdk-migration.mdc | 291 ------------------ .cursor/rules/test-memory-optimization.mdc | 146 +++++++++ AGENTS.md | 51 +++ app/AGENTS.md | 141 ++++++++- packages/mobile-sdk-alpha/AGENTS.md | 74 ++++- packages/mobile-sdk-alpha/README.md | 10 +- .../docs/MIGRATION_COMPLETED.md | 39 --- .../mobile-sdk-alpha/docs/MIGRATION_PLAN.md | 92 ------ .../docs/MIGRATION_PROMPTS.md | 110 ------- 9 files changed, 407 insertions(+), 547 deletions(-) delete mode 100644 .cursor/rules/mobile-sdk-migration.mdc create mode 100644 .cursor/rules/test-memory-optimization.mdc delete mode 100644 packages/mobile-sdk-alpha/docs/MIGRATION_COMPLETED.md delete mode 100644 packages/mobile-sdk-alpha/docs/MIGRATION_PLAN.md delete mode 100644 packages/mobile-sdk-alpha/docs/MIGRATION_PROMPTS.md diff --git a/.cursor/rules/mobile-sdk-migration.mdc b/.cursor/rules/mobile-sdk-migration.mdc deleted file mode 100644 index 7e90bf1eb..000000000 --- a/.cursor/rules/mobile-sdk-migration.mdc +++ /dev/null @@ -1,291 +0,0 @@ ---- -description: Comprehensive migration strategy and testing-first approach for porting identity verification logic from app to mobile-sdk-alpha package -version: 1.0.0 -status: active -owners: - - team: mobile-identity - - team: sdk-platform -lastUpdated: 2025-01-12 -specId: mobile-sdk-migration -importanceScore: 90 -importanceJustification: Critical framework for systematically migrating core identity verification functionality to a partner-consumable SDK while maintaining quality and testing coverage. -contextUsageNote: If this file is used to add in-context notes, include a single italicized line stating what specific information was used from this file in sentence case. ---- - -# Mobile SDK Migration Context - -## Migration Strategy Overview - -### Testing-First Approach -- **Create tests BEFORE migrating logic** to verify functionality works correctly -- **Dual testing environment**: Jest (app) + Vitest (mobile-sdk-alpha) -- **Validation commands**: `yarn test:build` in both app and mobile-sdk-alpha directories -- **Incremental migration**: One checklist item at a time with thorough validation - -### Test Environment Differences - -#### App (Jest) -- **Location**: `app/` directory -- **Config**: `jest.config.cjs` with React Native preset -- **Setup**: `jest.setup.js` with comprehensive mocks -- **Module mapping**: `@/` → `src/`, `@tests/` → `tests/src/` -- **Test command**: `yarn test:build` (builds deps + types + bundle analysis + tests) - -#### Mobile SDK Alpha (Vitest) -- **Location**: `packages/mobile-sdk-alpha/` directory -- **Config**: `vitest.config.ts` with Node environment -- **Setup**: `tests/setup.ts` with console noise suppression -- **Test command**: `yarn test:build` (build + test + types + lint) - -### Migration Validation Workflow - -1. **Pre-migration**: Create comprehensive tests in mobile-sdk-alpha for target functionality -2. **Migration**: Port logic from app to mobile-sdk-alpha -3. **Validation**: Run `yarn test:build` in both directories -4. **Integration**: Update app to consume mobile-sdk-alpha -5. **Final validation**: Ensure app tests pass with new SDK consumption - -## Migration Checklist Items - -### 1. Processing Helpers (MRZ) -**Current Location**: `app/src/utils/` (MRZ utilities) -**Target Location**: `packages/mobile-sdk-alpha/src/processing/` -**Testing Strategy**: -- Create MRZ parsing tests with sample passport data -- Test cross-platform compatibility (React Native vs Web) - -### 2. Validation Module -**Current Location**: `app/src/utils/` (document validation logic) -**Target Location**: `packages/mobile-sdk-alpha/src/validation/` -**Testing Strategy**: -- Unit tests for each validation rule -- Test with valid/invalid document data -- Test edge cases and error conditions - -### 3. Proof Input Generation -**Current Location**: `app/src/utils/proving/` -**Target Location**: `packages/mobile-sdk-alpha/src/proving/` -**Testing Strategy**: -- Test register input generation with mock data -- Test disclose input generation with various scenarios -- Validate TEE input format compliance - -### 4. Crypto Adapters -**Current Location**: `app/src/utils/` (crypto utilities) -**Target Location**: `packages/mobile-sdk-alpha/src/crypto/` -**Testing Strategy**: -- Test WebCrypto vs @noble/* fallback detection -- Test CSPRNG generation across platforms -- Test timing-safe comparison functions -- Parity tests between implementations - -### 5. TEE Session Management -**Current Location**: `app/src/utils/` (WebSocket handling) -**Target Location**: `packages/mobile-sdk-alpha/src/tee/` -**Testing Strategy**: -- Test WebSocket wrapper with mock server -- Test abort, timeout, and progress events -- Test connection lifecycle management - -### 6. Attestation Verification -**Current Location**: `app/src/utils/` (certificate validation) -**Target Location**: `packages/mobile-sdk-alpha/src/attestation/` -**Testing Strategy**: -- Test PCR0 validation with sample data -- Test public key extraction -- Test certificate chain validation - -### 7. Protocol Synchronization -**Current Location**: `app/src/utils/` (protocol tree handling) -**Target Location**: `packages/mobile-sdk-alpha/src/protocol/` -**Testing Strategy**: -- Test protocol tree fetching with pagination -- Test TTL cache behavior -- Test rate limiting and exponential backoff -- Test memory bounds enforcement - -### 8. Artifact Management -**Current Location**: `app/src/utils/` (manifest handling) -**Target Location**: `packages/mobile-sdk-alpha/src/artifacts/` -**Testing Strategy**: -- Test manifest schema validation -- Test CDN download with caching -- Test signature verification -- Test storage adapter integration - -### 9. Sample Applications -**Target Location**: `packages/mobile-sdk-alpha/samples/` -**Testing Strategy**: -- Create React Native demo with MRZ → proof flow -- Create web demo with browser-based MRZ input -- Test iOS `OpenPassport` URL scheme - -### 10. SDK Integration into App -**Migration Strategy**: -- Replace existing modules with SDK imports -- Update import paths throughout app -- Validate all existing functionality works -- Ensure no regression in app behavior - -### 11. In-SDK Lightweight Demo -**Target Location**: `packages/mobile-sdk-alpha/demo/` -**Testing Strategy**: -- Embedded React Native demo using MRZ → proof flow -- Test theming hooks integration -- Validate build and run instructions - -## Testing Best Practices - -### Test Data Management -- **Mock data**: Create comprehensive test fixtures for each module -- **Sensitive data**: Never log PII, credentials, or private keys -- **Redaction**: Use consistent patterns for sensitive field masking -- **Environment flags**: Use `DEBUG_SECRETS_TOKEN` for debug-level secrets - -### Cross-Platform Testing -- **React Native**: Test on both iOS and Android simulators -- **Web**: Test with browser adapters -- **Platform detection**: Test platform-specific code paths -- **Native modules**: Mock native dependencies appropriately - -### Performance Testing -- **Bundle size**: Monitor SDK bundle size impact -- **Memory usage**: Test memory bounds for large operations -- **Network efficiency**: Test rate limiting and caching -- **Startup time**: Measure SDK initialization impact - -### Integration Testing -- **End-to-end flows**: Test complete user journeys -- **Error handling**: Test graceful degradation -- **Recovery mechanisms**: Test error recovery and retry logic -- **Backward compatibility**: Ensure existing app functionality works - -## Migration Validation Checklist - -### Pre-Migration -- [ ] Create comprehensive test suite in mobile-sdk-alpha -- [ ] Define test fixtures and mock data -- [ ] Set up cross-platform testing environment -- [ ] Document current functionality and edge cases - -### During Migration -- [ ] Port logic incrementally (one checklist item at a time) -- [ ] Run `yarn test:build` in mobile-sdk-alpha after each item -- [ ] Validate functionality matches original implementation -- [ ] Update documentation and type definitions -- [ ] Re-export new modules via `packages/mobile-sdk-alpha/src/index.ts` and document them in `packages/mobile-sdk-alpha/README.md` - -### Post-Migration -- [ ] Update app to consume mobile-sdk-alpha -- [ ] Run `yarn test:build` in app directory -- [ ] Validate all existing app tests pass -- [ ] Test integration with existing app functionality -- [ ] Performance validation and bundle size analysis - -### Final Validation -- [ ] End-to-end testing of complete flows -- [ ] Cross-platform compatibility verification -- [ ] Partner SDK consumption testing -- [ ] Documentation and example updates -- [ ] Release preparation and versioning - -## Common Migration Patterns - -### Module Structure -```typescript -// Before (app/src/utils/module.ts) -export function processData(data: InputType): OutputType { - // Implementation -} - -// After (packages/mobile-sdk-alpha/src/module/index.ts) -export function processData(data: InputType): OutputType { - // Same implementation with enhanced error handling -} - -// Test (packages/mobile-sdk-alpha/tests/module.test.ts) -describe('processData', () => { - it('should process valid data correctly', () => { - // Test implementation - }); -}); -``` - -### Adapter Pattern -```typescript -// Cross-platform adapter interface -export interface ScannerAdapter { - scan(): Promise; - isSupported(): boolean; -} - -// Platform-specific implementations -export class ReactNativeScannerAdapter implements ScannerAdapter { - // React Native implementation -} - -export class WebScannerAdapter implements ScannerAdapter { - // Web implementation -} -``` - -### Error Handling -```typescript -// Consistent error types across SDK -export class SDKError extends Error { - constructor( - message: string, - public code: string, - public details?: Record - ) { - super(message); - this.name = 'SDKError'; - } -} -``` - -## Security & Privacy Considerations - -### Data Protection -- **Sensitive data**: Never log PII, credentials, or private keys in production -- **Secure storage**: Use appropriate storage mechanisms for sensitive data -- **Cleanup**: Properly clean up sensitive data after use -- **Validation**: Validate all inputs and outputs for security - -### Privacy Features -- **Zero-knowledge proofs**: Ensure privacy-preserving verification -- **Selective disclosure**: Support minimal necessary attribute revelation -- **Identity commitments**: Maintain privacy of identity data -- **Audit trails**: Log access to sensitive operations without exposing data - -## Performance Optimization - -### Bundle Size -- **Tree shaking**: Ensure all exports support tree shaking -- **Code splitting**: Split large modules into smaller chunks -- **Dependency analysis**: Monitor and optimize dependencies -- **Bundle analysis**: Regular bundle size monitoring - -### Runtime Performance -- **Lazy loading**: Load modules only when needed -- **Caching**: Implement appropriate caching strategies -- **Memory management**: Prevent memory leaks in long-running operations -- **Async operations**: Use proper async patterns for non-blocking operations - -## Partner SDK Requirements - -### API Design -- **Consistent interfaces**: Maintain consistent API patterns -- **Type safety**: Provide comprehensive TypeScript definitions -- **Error handling**: Clear error messages and error codes -- **Documentation**: Comprehensive API documentation - -### Integration Support -- **Branding**: Support for partner branding and theming -- **Callbacks**: Async operation callbacks for integration -- **Configuration**: Flexible configuration options -- **Examples**: Comprehensive integration examples - -This context provides a comprehensive framework for executing the migration checklist with a testing-first approach, ensuring quality and reliability throughout the migration process. - -$END$ diff --git a/.cursor/rules/test-memory-optimization.mdc b/.cursor/rules/test-memory-optimization.mdc new file mode 100644 index 000000000..d54bfce4e --- /dev/null +++ b/.cursor/rules/test-memory-optimization.mdc @@ -0,0 +1,146 @@ +--- +description: Critical rules for avoiding out-of-memory issues in tests, specifically preventing nested require() calls that cause pipeline failures +version: 1.0.0 +status: active +owners: + - team: mobile-identity + - team: platform-infrastructure +lastUpdated: 2025-01-12 +specId: test-memory-optimization +importanceScore: 100 +importanceJustification: Prevents catastrophic pipeline failures due to out-of-memory errors caused by nested require() calls, especially with react-native modules in test environments. +contextUsageNote: If this file is used to add in-context notes, include a single italicized line stating what specific information was used from this file in sentence case. +--- + +# Test Memory Optimization Rules + +## Critical: Never Nest require() Calls + +### The Problem + +Nested `require('react-native')` calls within tests cause **out-of-memory (OOM) errors** in CI/CD pipelines. This happens because: + +1. **Module Resolution Loops**: Each nested require can trigger additional module resolution and initialization +2. **Memory Accumulation**: React Native modules are large and complex; nested requires multiply memory usage +3. **Test Environment Overhead**: Jest/Vitest test runners already load modules; nested requires create duplicate module instances +4. **Hermes Parser Issues**: Nested requires can trigger WASM memory issues with hermes-parser + +### The Rule + +**NEVER create nested `require('react-native')` calls within test files or test setup files.** + +### Examples of FORBIDDEN Patterns + +#### ❌ FORBIDDEN: Nested require in test files +```typescript +// BAD - This will cause OOM issues +describe('MyComponent', () => { + beforeEach(() => { + const RN = require('react-native'); + const Component = require('./MyComponent'); + // Component internally does: require('react-native') again + // This creates nested requires = OOM + }); +}); +``` + +#### ❌ FORBIDDEN: require() inside module that's required in tests +```typescript +// BAD - If this module is required in tests, it creates nested requires +// app/src/utils/myUtil.ts +export function myFunction() { + const RN = require('react-native'); // Nested if called from test + return RN.Platform.OS; +} +``` + +#### ❌ FORBIDDEN: Dynamic requires in test hooks +```typescript +// BAD - Dynamic requires in beforeEach/afterEach create nested requires +beforeEach(() => { + jest.resetModules(); + const RN = require('react-native'); // First require + const service = require('@/utils/service'); // May internally require RN again +}); +``` + +### Examples of CORRECT Patterns + +#### ✅ CORRECT: Use ES6 imports at top level +```typescript +// GOOD - Single import at top level +import { Platform } from 'react-native'; + +describe('MyComponent', () => { + it('should work', () => { + expect(Platform.OS).toBe('ios'); + }); +}); +``` + +**Key Rule**: Use `import` statements, not `require()`. React Native is already mocked in setup files (`jest.setup.js` for Jest, `tests/setup.ts` for Vitest), so imports work correctly. + +## React Native Module Handling in Tests + +### Jest Setup Pattern (app/jest.setup.js) + +The project uses a custom require override in `jest.setup.js` to handle React Native mocks: + +```javascript +// This is OK - it's in setup file, runs once +const Module = require('module'); +const originalRequire = Module.prototype.require; +Module.prototype.require = function (id) { + if (id === 'react-native') { + const RN = originalRequire.apply(this, arguments); + // Add mocks if needed + return RN; + } + return originalRequire.apply(this, arguments); +}; +``` + +**Key Point**: This override runs ONCE during test setup. Tests should NOT create additional require() calls that would trigger this override multiple times. + +### Vitest Setup Pattern (packages/mobile-sdk-alpha/tests/setup.ts) + +Vitest uses `vi.mock()` to mock React Native: + +```typescript +// This is OK - runs once during setup +vi.mock('react-native', () => ({ + Platform: { OS: 'web' }, + // ... other mocks +})); +``` + +**Key Point**: Tests should use `import` statements, not `require()`, after mocks are set up. + +## Best Practices + +1. **Always use ES6 `import` statements** - Never use `require('react-native')` in test files +2. **Put all imports at the top of the file** - No dynamic imports in hooks +3. **Avoid `jest.resetModules()`** - Only use when absolutely necessary for module initialization tests +4. **Use setup file mocks** - React Native is already mocked in `jest.setup.js` (Jest) or `tests/setup.ts` (Vitest) + +## Quick Checklist + +Before committing test changes: +- [ ] No `require('react-native')` calls in test files (use `import` instead) +- [ ] All imports at top of file (not in hooks) +- [ ] Search for nested patterns: `grep -r "require('react-native')" app/tests/` + +## Detection + +**Signs of nested require issues**: CI OOM errors, test timeouts, memory spikes, "Call stack size exceeded" errors + +**Fix**: Search for `require('react-native')` in tests → Replace with `import` statements + +## Related Files + +- `app/jest.setup.js` - Jest setup with React Native mocks +- `packages/mobile-sdk-alpha/tests/setup.ts` - Vitest setup with React Native mocks +- `app/jest.config.cjs` - Jest configuration +- `packages/mobile-sdk-alpha/vitest.config.ts` - Vitest configuration + +$END$ diff --git a/AGENTS.md b/AGENTS.md index 9ecbb8785..836d09fae 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -130,6 +130,20 @@ yarn types # Verify type checking - For Noir circuits, run `nargo test -p ` in each `noir/crates/*` directory. - Tests for `@selfxyz/contracts` are currently disabled in CI and may be skipped. +- E2E tests (mobile app) - **Run automatically in CI/CD, not required locally**: + - E2E tests execute automatically in GitHub Actions on PRs and main branch + - Local E2E testing is optional (see `app/AGENTS.md` for local setup if needed) + - Commands available: `yarn workspace @selfxyz/mobile-app test:e2e:ios` / `test:e2e:android` + +#### Test Memory Optimization + +**CRITICAL**: Never create nested `require('react-native')` calls in tests. This causes out-of-memory (OOM) errors in CI/CD pipelines. + +- Use ES6 `import` statements instead of `require()` when possible +- Avoid dynamic `require()` calls in `beforeEach`/`afterEach` hooks +- Prefer top-level imports over nested requires +- See `.cursor/rules/test-memory-optimization.mdc` for detailed guidelines + ### CI Caching Use the shared composite actions in `.github/actions` when caching dependencies in GitHub workflows. They provide consistent cache paths and keys: @@ -151,6 +165,43 @@ Each action accepts an optional `cache-version` input (often combined with `GH_C - Write short, imperative commit messages (e.g. `Fix address validation`). - The pull request body should summarize the changes and mention test results. +## Workspace-Specific Instructions + +Some workspaces have additional instructions in their own `AGENTS.md` files: + +- `app/AGENTS.md` - Mobile app development, E2E testing, deployment +- `packages/mobile-sdk-alpha/AGENTS.md` - SDK development, testing guidelines, package validation +- `noir/AGENTS.md` - Noir circuit development + +These workspace-specific files override or extend the root instructions for their respective areas. + +## Troubleshooting + +### Common Issues + +#### Yarn Install Fails + +- Ensure Node.js 22.x is installed: `nvm use` +- Clear Yarn cache: `yarn cache clean` +- Remove `node_modules` and reinstall: `rm -rf node_modules && yarn install` + +#### Build Failures + +- Run `yarn build:deps` in affected workspace first +- Check workspace-specific `AGENTS.md` for platform requirements +- For mobile app: ensure iOS/Android prerequisites are met (see `app/AGENTS.md`) + +#### Test Failures + +- Check workspace-specific test setup requirements +- For mobile app tests: ensure native modules are properly mocked +- See `.cursor/rules/test-memory-optimization.mdc` for test memory issues + +#### Type Errors + +- Run `yarn types` to see all type errors across workspaces +- Some packages may need to be built first: `yarn build:deps` + ## Scope These instructions apply to the entire repository unless overridden by a nested `AGENTS.md`. diff --git a/app/AGENTS.md b/app/AGENTS.md index e4aa6d220..938fb8da9 100644 --- a/app/AGENTS.md +++ b/app/AGENTS.md @@ -18,6 +18,7 @@ Before creating a PR for the mobile app: - [ ] `yarn nice` passes (fixes linting and formatting) - [ ] `yarn types` passes (TypeScript validation) - [ ] `yarn test` passes (unit tests) +- [ ] No nested `require('react-native')` calls in tests (causes OOM in CI) - check with `grep -r "require('react-native')" app/tests/` and verify no nested patterns - [ ] App builds successfully on target platforms ### Mobile-Specific Validation @@ -25,12 +26,14 @@ Before creating a PR for the mobile app: - [ ] Android build succeeds: `yarn android` (emulator/device) - [ ] Web build succeeds: `yarn web` - [ ] No sensitive data in logs (PII, credentials, tokens) +- [ ] Environment variables properly configured (check `.env` setup) +- [ ] E2E tests run in CI (not required locally - CI will run E2E tests automatically) ### AI Review Preparation - [ ] Complex native module changes documented - [ ] Platform-specific code paths explained - [ ] Security-sensitive operations flagged -- [ ] Performance implications noted +- [ ] Performance implications noted (including test memory patterns if tests were modified) ## Post-PR Validation @@ -45,8 +48,11 @@ After PR creation: ### Mobile-Specific Checks - [ ] App launches without crashes - [ ] Core functionality works on target platforms -- [ ] No memory leaks introduced +- [ ] No memory leaks introduced (including test memory patterns - see Test Memory Optimization section) - [ ] Bundle size within acceptable limits +- [ ] No nested `require('react-native')` calls in tests (causes OOM in CI) +- [ ] Native modules work correctly (if native code was modified) +- [ ] Platform-specific code paths tested (iOS/Android/Web) ### Review Integration - [ ] Address CodeRabbitAI feedback @@ -92,4 +98,133 @@ yarn types # Verify type checking ## Running the App -- `yarn ios` +- `yarn ios` - Run on iOS simulator (builds dependencies automatically) +- `yarn android` - Run on Android emulator/device (builds dependencies automatically) +- `yarn web` - Run web version + +### Development Tips + +- Use `yarn build:deps` to build all workspace dependencies before running the app +- For iOS: Ensure Xcode scheme is set to "OpenPassport" (see memory) +- For Android: Ensure emulator is running or device is connected before `yarn android` +- Metro bundler starts automatically; use `yarn start` to run it separately + +## E2E Testing + +The app uses Maestro for end-to-end testing. **E2E tests run automatically in CI/CD pipelines - they are not required to run locally.** + +### CI/CD E2E Testing + +- E2E tests run automatically in GitHub Actions workflows +- iOS and Android E2E tests run on PRs and main branch +- No local setup required - CI handles all E2E test execution + +### Local E2E Testing (Optional) + +If you need to run E2E tests locally for debugging: + +**Prerequisites:** +- Maestro CLI installed: `curl -Ls "https://get.maestro.mobile.dev" | bash` +- iOS: Simulator running or device connected +- Android: Emulator running or device connected +- App built and installed on target device/simulator + +**Running Locally:** +```bash +# iOS E2E tests +yarn test:e2e:ios + +# Android E2E tests +yarn test:e2e:android + +# Or use the local test script (handles setup automatically) +./scripts/test-e2e-local.sh ios +./scripts/test-e2e-local.sh android +``` + +**E2E Test Files:** +- iOS: `tests/e2e/launch.ios.flow.yaml` +- Android: `tests/e2e/launch.android.flow.yaml` + +## Environment Variables + +The app uses `react-native-dotenv` for environment configuration. + +### Setup + +- Create `.env` file in `app/` directory (see `.env.example` if available) +- Environment variables are loaded via `@env` import +- For secrets: Use `.env.secrets` (gitignored) for local development +- In CI: Environment variables are set in workflow files + +### Common Environment Variables + +- `GOOGLE_SIGNIN_ANDROID_CLIENT_ID` - Google Sign-In configuration +- Various API endpoints and keys (check `app/env.ts` for full list) + +### Testing with Environment Variables + +- Tests use mocked environment variables (see `jest.setup.js`) +- E2E tests use actual environment configuration +- Never commit `.env.secrets` or sensitive values + +## Deployment + +### Mobile Deployment + +The app uses Fastlane for iOS and Android deployment. + +### Deployment Commands + +```bash +# Deploy both platforms (requires confirmation) +yarn mobile-deploy + +# Deploy iOS only +yarn mobile-deploy:ios + +# Deploy Android only +yarn mobile-deploy:android + +# Force local deployment (for testing deployment scripts) +yarn mobile-local-deploy +``` + +### Deployment Prerequisites + +- See `app/docs/MOBILE_DEPLOYMENT.md` for detailed deployment guide +- Required secrets configured in CI/CD or `.env.secrets` for local +- iOS: App Store Connect API keys, certificates, provisioning profiles +- Android: Play Store service account, keystore + +### Deployment Checklist + +- [ ] Version bumped in `package.json` and `app.json` +- [ ] Changelog updated +- [ ] All unit tests pass (`yarn test`) +- [ ] Build succeeds for target platform +- [ ] Required secrets/environment variables configured +- [ ] Fastlane configuration verified +- [ ] CI E2E tests pass (automatically run in CI, no local action needed) + +## Test Memory Optimization + +**CRITICAL**: Never create nested `require('react-native')` calls in tests. This causes out-of-memory (OOM) errors in CI/CD pipelines. + +### Quick Check +Before committing, verify no nested requires: +```bash +# Check for require('react-native') in test files +grep -r "require('react-native')" app/tests/ + +# Review results - ensure no nested patterns (require inside beforeEach/afterEach or inside modules that are required in tests) +``` + +### Best Practices +- Use ES6 `import` statements instead of `require()` when possible +- Avoid dynamic `require()` calls in `beforeEach`/`afterEach` hooks +- Prefer top-level imports over nested requires +- React Native is already mocked in `jest.setup.js` - use imports in test files + +### Detailed Guidelines +See `.cursor/rules/test-memory-optimization.mdc` for comprehensive guidelines, examples, and anti-patterns. diff --git a/packages/mobile-sdk-alpha/AGENTS.md b/packages/mobile-sdk-alpha/AGENTS.md index c3b3f03fd..871140c3b 100644 --- a/packages/mobile-sdk-alpha/AGENTS.md +++ b/packages/mobile-sdk-alpha/AGENTS.md @@ -75,11 +75,13 @@ Before creating a PR for the mobile-sdk-alpha package: ### SDK-Specific Validation -- [ ] Exports are properly configured -- [ ] Package conditions are valid +- [ ] Exports are properly configured (`yarn validate:exports`) +- [ ] Package conditions are valid (`yarn validate:pkg`) - [ ] No breaking changes to public API (or properly documented) - [ ] Migration guide updated (if applicable) - [ ] Integration tests pass +- [ ] SDK integration with main app verified (if API changed) +- [ ] Cross-platform compatibility verified (React Native + Web) ### AI Review Preparation @@ -102,9 +104,12 @@ After PR creation: ### SDK-Specific Checks - [ ] Package exports validation passes -- [ ] Integration with main app still works +- [ ] Integration with main app still works (tested in `@selfxyz/mobile-app`) - [ ] No circular dependencies introduced - [ ] Bundle size impact acceptable +- [ ] No nested `require('react-native')` calls in tests (causes OOM in CI) +- [ ] Cross-platform compatibility maintained (React Native + Web) +- [ ] Type definitions are complete and accurate ### Review Integration @@ -144,6 +149,28 @@ yarn build # Confirm build still works - Prettier is used for code formatting - The `yarn nice` command is the recommended way to fix code quality issues - Use the root Prettier and EditorConfig settings for consistency +- Uses Vitest for testing (not Jest) - see `tests/setup.ts` for configuration +- React Native is mocked for web compatibility in tests + +## Integration Testing + +### Testing SDK Integration with Main App + +When making changes to the SDK API, verify integration: + +```bash +# From app directory +cd ../../app +yarn build:deps # Ensures latest SDK is built +yarn test # Run app tests that use SDK +``` + +### Cross-Platform Considerations + +- SDK must work in both React Native and Web environments +- Use platform detection when needed: `Platform.OS === 'web'` +- Test both environments when adding platform-specific code +- Vitest tests run in Node.js environment (mocked React Native) ## Testing Guidelines @@ -184,3 +211,44 @@ describe('Real SDK Integration', () => { ``` **⚠️ CRITICAL: Never use real user PII in tests. Use only synthetic, anonymized, or approved test vectors.** + +## Test Memory Optimization + +**CRITICAL**: Never create nested `require('react-native')` calls in tests. This causes out-of-memory (OOM) errors in CI/CD pipelines. + +### Key Rules + +- Use ES6 `import` statements instead of `require()` when possible +- Avoid dynamic `require()` calls in `beforeEach`/`afterEach` hooks +- Prefer top-level imports over nested requires +- This package uses Vitest (not Jest), but the same principles apply +- React Native is already mocked in `tests/setup.ts` using `vi.mock()` - use imports in test files + +### Example Patterns + +#### ✅ CORRECT: Use ES6 imports + +```ts +// GOOD - Single import at top level +import { Platform } from 'react-native'; + +describe('MyComponent', () => { + it('should work', () => { + expect(Platform.OS).toBe('web'); + }); +}); +``` + +#### ❌ FORBIDDEN: Nested requires + +```ts +// BAD - This will cause OOM issues +describe('MyComponent', () => { + beforeEach(() => { + const RN = require('react-native'); // First require + const Component = require('./MyComponent'); // May internally require RN again = nested = OOM + }); +}); +``` + +See `.cursor/rules/test-memory-optimization.mdc` for detailed guidelines and more examples. diff --git a/packages/mobile-sdk-alpha/README.md b/packages/mobile-sdk-alpha/README.md index 3aa2542b2..cc9401faa 100644 --- a/packages/mobile-sdk-alpha/README.md +++ b/packages/mobile-sdk-alpha/README.md @@ -251,19 +251,11 @@ The SDK surfaces typed errors for clearer diagnostics: All errors extend `SdkError`, which includes a `code`, `category`, and `retryable` flag. -## Migration plan - -Track remaining tasks in [MIGRATION_PLAN.md](./docs/MIGRATION_PLAN.md) and see completed work in [MIGRATION_COMPLETED.md](./docs/MIGRATION_COMPLETED.md). - -## Architecture - -Migration and architecture prompts live in [PROMPTS.md](./docs/PROMPTS.md). - ## Testing **IMPORTANT: Do NOT mock this package in tests!** -The purpose of the mobile-sdk-alpha migration is to test the REAL package methods, not mocked versions. When integrating this package into your application: +Use the REAL package methods, not mocked versions. When integrating this package into your application: ### ✅ DO: Use Real Package Methods (PII-safe) diff --git a/packages/mobile-sdk-alpha/docs/MIGRATION_COMPLETED.md b/packages/mobile-sdk-alpha/docs/MIGRATION_COMPLETED.md deleted file mode 100644 index 963a6aa21..000000000 --- a/packages/mobile-sdk-alpha/docs/MIGRATION_COMPLETED.md +++ /dev/null @@ -1,39 +0,0 @@ -# Completed Mobile SDK Migration Tasks - -This log captures what’s already landed. Everything still in flight lives in [MIGRATION_PLAN.md](./MIGRATION_PLAN.md). - -## Migration - -### 1. MRZ processing helpers - -- MRZ utilities are in place and re‑exported through the SDK. -- The code now lives under `src/mrz/` and `src/qr/`. -- `notImplemented` guards unfinished paths. -- Type aliases keep things lean. - -### 2. Validation module - -- Stateless document checks were ported and covered by unit tests. - -### 3. Integrate SDK into `/app` - -- The `app` workspace consumes `@selfxyz/mobile-sdk-alpha`. -- Screens are wired to SDK processing and validation helpers. - -## Architecture - -### 1. Modular feature directories - -- New capabilities sit in dedicated folders and are re‑exported via `src/index.ts`. -- Error paths use `notImplemented`. -- Type aliases replaced empty interfaces. - -### 2. Bridge layer for native events - -- `NativeModules` and `NativeEventEmitter` are wrapped in a shared adapter. -- Platforms share a unified event interface. - -### 3. Exception classes - -- Added typed errors (`InitError`, `LivenessError`, `NfcParseError`, `MrzParseError`). -- The SDK now surfaces these instead of generic `Error`. diff --git a/packages/mobile-sdk-alpha/docs/MIGRATION_PLAN.md b/packages/mobile-sdk-alpha/docs/MIGRATION_PLAN.md deleted file mode 100644 index f1929b70f..000000000 --- a/packages/mobile-sdk-alpha/docs/MIGRATION_PLAN.md +++ /dev/null @@ -1,92 +0,0 @@ -# Mobile SDK Migration Plan - -This is the running to‑do list for the mobile SDK. When you wrap up a task, move it to [MIGRATION_COMPLETED.md](./MIGRATION_COMPLETED.md) so we keep a record. - -## Migration tasks - -### 3. Bring the SDK into `/app` - -- [ ] Swap the MRZ modules for the SDK’s adapters -- [ ] Make sure the app still builds and the unit tests pass - -### 4. Generate proof inputs - -- [ ] Port helpers that prep register and disclose inputs for the TEE - -### 5. Crypto adapters - -- [ ] Pick WebCrypto or noble at runtime -- [ ] Cross‑check outputs between the two -- [ ] Detect WebCrypto support when running on React Native/Hermes -- [ ] Guarantee random bytes come from a CSPRNG -- [ ] Compare secrets with a timing-safe helper - -### 6. TEE session management - -- [ ] Wrap WebSockets so we can handle aborts, timeouts, and progress events - -### 7. Attestation verification - -- [ ] Check PCR0 and extract the public key -- [ ] Add a lightweight certificate chain check - -### 8. Protocol synchronization - -- [ ] Fetch protocol trees with pagination and a short TTL cache -- [ ] Verify computed roots against server data -- [ ] Rate‑limit with exponential backoff and jitter -- [ ] Cap memory use and honor `Retry‑After` headers - -### 9. React Native providers and hooks - -- [ ] Decouple context providers and hooks from adapter implementations -- [ ] Move `SelfClientProvider` and its adapters into the SDK, exposing adapter props -- [ ] Accept adapter instances via props to avoid tight coupling -- [ ] Map provider boundaries to the architecture tasks for crypto, sessions, attestation, protocol sync, and artifacts - -### 10. Batteries‑included components - -- [ ] Ship minimal components (e.g., scanners, buttons) that compose existing hooks and providers -- [ ] Expose configuration props for custom adapters while keeping sensible defaults -- [ ] Link component usage to architecture guidelines and adapter tasks - -### 11. Sample applications - -- [ ] React Native and web demos showcasing core flows -- [ ] iOS `OpenPassport` URL scheme - -### 12. In‑SDK lightweight demo - -- [ ] Embed a small React Native demo inside the SDK with theming hooks -- [ ] Provide build and run instructions - -## Architecture tasks - -### 4. Manage the SDK lifecycle - -- [ ] Turn `createSelfClient` into a class -- [ ] Add `initialize()` and `deinitialize()` hooks -- [ ] Keep config on the instance instead of globals - -### 5. Package targets - -- [ ] Keep the React Native build first -- [ ] Add entry points for web builds -- [ ] Lay groundwork for future targets like Capacitor or Cordova - -### 6. Dogfood in `/app` - -- [ ] Validate real flows -- [ ] Replace MRZ modules with SDK adapters - -### 7. Android demo app - -- [ ] Ship a minimal React Native Android project -- [ ] Demonstrate MRZ → proof generation flow -- [ ] Provide build and run instructions - -## Consolidation toward `@selfxyz/common` - -- [ ] Pull document catalog helpers and keychain wrappers out of the app and into `@selfxyz/common` -- [ ] Share analytics and auth adapters through a common or dedicated package -- [ ] Re-export storage types so other apps can reuse them without the mobile app context diff --git a/packages/mobile-sdk-alpha/docs/MIGRATION_PROMPTS.md b/packages/mobile-sdk-alpha/docs/MIGRATION_PROMPTS.md deleted file mode 100644 index 9bb1d1f49..000000000 --- a/packages/mobile-sdk-alpha/docs/MIGRATION_PROMPTS.md +++ /dev/null @@ -1,110 +0,0 @@ -# Task Prompts - -This file offers quick pointers for anyone picking up work from the [migration plan](./MIGRATION_PLAN.md). Use it to get oriented, then dive into the code. - -## Pre-flight checks - -Run these before opening a PR: - -```bash -yarn workspace @selfxyz/mobile-sdk-alpha nice -yarn workspace @selfxyz/mobile-sdk-alpha types -yarn workspace @selfxyz/mobile-sdk-alpha test -yarn workspace @selfxyz/mobile-sdk-alpha build -yarn lint -yarn build -``` - -## Migration tasks - -### 3. Integrate SDK into `/app` - -- In `app/src/providers/passportDataProvider.tsx` replace local MRZ helpers with `extractMRZInfo` from `@selfxyz/mobile-sdk-alpha/mrz` and `parseNFCResponse` from `@selfxyz/mobile-sdk-alpha/nfc`. -- Update `app/src/components/native/PassportCamera.tsx` and `app/src/utils/nfcScanner.ts` to use the SDK exports. -- Run `yarn workspace @selfxyz/mobile-app build && yarn workspace @selfxyz/mobile-app test`. - -### 4. Proof input generation - -- Move `generateTEEInputsRegister` and `generateTEEInputsDisclose` from `app/src/utils/proving/provingInputs.ts` into new files under `packages/mobile-sdk-alpha/src/proving/register.ts` and `packages/mobile-sdk-alpha/src/proving/disclose.ts`. -- Replace `useProtocolStore` with a `getTree(document, kind)` callback so helpers are stateless. -- Add tests in `packages/mobile-sdk-alpha/tests/proving.{register,disclose}.test.ts`. - -### 5. Crypto adapters - -- Create `src/adapters/crypto/index.ts` exporting a `CryptoAdapter` interface with `getRandomValues`, `digest` and `timingSafeEqual`. -- Implement `src/adapters/crypto/webcrypto.ts` and `src/adapters/crypto/noble.ts` and wire runtime detection in `src/adapters/crypto/index.ts`. -- Add parity tests in `tests/crypto.test.ts` ensuring both adapters produce identical results. - -### 6. TEE session management - -- Implement `WsAdapter` in `src/adapters/ws/websocket.ts` wrapping `WebSocket` with abort, timeout, and progress callbacks. -- Export the adapter through `src/adapters/index.ts`. -- Add tests under `tests/ws.test.ts` using a mocked server in `tests/ws.server.ts`. - -### 7. Attestation verification - -- Port `parseCertificateSimple` and PCR0 utilities from `common/src/utils/certificate_parsing/` into `src/attestation/verify.ts`. -- Expose `verifyAttestation(cert: ArrayBuffer, quote: ArrayBuffer)` that returns the public key. -- Cover the verifier with unit tests in `tests/attestation.test.ts`. - -### 8. Protocol synchronization - -- Add `src/protocol/sync.ts` with `fetchProtocolTrees(fetchPage, cache)` to paginate and cache trees. -- Verify roots against `@selfxyz/common/utils/proving` and honor `Retry-After` headers. -- Write tests in `tests/protocol.test.ts` with a fake server. - -### 9. React Native providers and hooks - -- Move `app/src/providers/selfClientProvider.tsx` into `src/context.tsx` and expose a `SelfClientProvider` that accepts adapter instances (`crypto`, `ws`, `storage`, `logger`). -- Add hooks like `useSelfClient` and `useDocuments` in `src/hooks/`. -- Remove the wrapper from the app and import the provider directly from the SDK. - -### 10. Batteries-included components - -- Create `src/components/Scanner.tsx` using `useScanner` and `SelfClientProvider`. -- Add `src/components/ScanButton.tsx` that triggers MRZ and NFC flows with optional adapter props. -- Document usage in `docs/components.md`. - -### 11. Sample applications - -- Scaffold `examples/react-native/` and `examples/web/` showcasing scan → proof flows. -- Include iOS `OpenPassport` URL scheme setup in `examples/react-native/README.md`. -- Ensure both samples use the published SDK rather than local files. - -### 12. In-SDK lightweight demo - -- Add `demo/` inside the package with `App.tsx` using `SelfClientProvider` and theming hooks. -- Provide run instructions in `demo/README.md` for `yarn demo ios` and `yarn demo android`. -- Wire demo entry in `package.json` scripts. - -## Architecture tasks - -### 4. SDK lifecycle management - -- Refactor `src/client.ts` so `createSelfClient` becomes `class SelfClient` with `initialize()` and `deinitialize()` methods. -- Persist configuration on the instance rather than module globals. -- Update exports in `src/index.ts`. - -### 5. Package targets - -- Add a `"./web"` entry to `package.json#exports` pointing to `dist/web/index.js` while keeping React Native as the default. -- Update `tsup.config.ts` to produce a web build target. -- Note possible future targets (Capacitor, Cordova) in comments. - -### 6. Dogfood in `/app` - -- Update `app/src/utils/proving/provingMachine.ts` and screens in `app/src/screens/prove/` to consume SDK methods. -- Remove deprecated MRZ utilities from the app and import from `@selfxyz/mobile-sdk-alpha`. -- Confirm flows via `yarn workspace @selfxyz/mobile-app test`. - -### 7. Android demo app - -- Create `examples/android-demo/` with React Native CLI, wiring scanning and proof generation through the SDK. -- Provide setup instructions in `examples/android-demo/README.md`. -- Link the demo in the main `README.md`. - -## Consolidation toward `@selfxyz/common` - -- Move `calculateContentHash` and related catalog helpers from `app/src/providers/passportDataProvider.tsx` to `common/src/utils/documents/` and re-export via `@selfxyz/common`. -- Pull keychain wrappers like `storeDocument` into `common/src/utils/storage/passport.ts`. -- Publish shared analytics/auth adapters (currently in `app/src/utils/analytics.ts` and `app/src/providers/authProvider.tsx`) through a new package and re-export types from `@selfxyz/common`.