M4 phase2#9
Merged
Merged
Conversation
M4 Phase 3 - Detox validation, integration tests and device testing
There was a problem hiding this comment.
Pull request overview
This PR advances the OfflineFaceAuth “M4” work by moving the offline sync queue from an in-memory stub to a SQLCipher-backed sync_queue table, wiring a Phase 2 S3 upload path + retrying sync worker, and adding supporting test suites and deployment artifacts for Day-17 Go/No-Go validation.
Changes:
- Add SQLCipher migration + queue read/write helpers (
sync_queue) and update sync worker/purge logic to use DB-backed status transitions. - Introduce a real S3 upload function (
uploadToS3) alongside the existing stub, and add AWS Lambda + CloudFormation deployment assets. - Add/expand integration + Detox E2E tests and Go/No-Go checklists/reports for validation evidence.
Reviewed changes
Copilot reviewed 35 out of 38 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/PHYSICAL_DEVICE_CHECKLIST.md | Adds a physical-device validation matrix and manual test steps for Day-17 gates. |
| tests/integration/verification-flow.test.ts | Adds Jest integration tests for queue reading/processing flow (currently still assumes in-memory queue). |
| tests/integration/tamper-detection.test.ts | Adds Jest tests for tamper-detection chain verification logic (test-local implementation). |
| tests/integration/sync-flow.test.ts | Adds Jest tests for offline queue + upload stub coordination (currently still assumes in-memory queue). |
| tests/integration/enrollment-flow.test.ts | Adds Jest integration tests around SQLCipher open/migrations using module mocks. |
| tests/INTEGRATION_TEST_REPORT.md | Documents claimed Jest integration run results and coverage mapping to Go/No-Go criteria. |
| tests/GO_NO_GO_CHECKLIST.md | Adds Day-17 Go/No-Go checklist and evidence links. |
| tests/fixtures/mock-landmarks.json | Replaces placeholder with structured mock FaceMesh landmark scenarios for tests. |
| tests/fixtures/mock-embeddings.json | Replaces placeholder with structured mock MobileFaceNet embeddings for tests. |
| tests/e2e/verification.e2e.ts | Adds Detox verification-harness UI assertions. |
| tests/e2e/enrollment.e2e.ts | Adds Detox enrollment-harness UI assertions. |
| tests/e2e/antispoof.e2e.ts | Adds Detox antispoof UI assertions (emulator-oriented expectations). |
| tests/e2e/airplane-mode.e2e.ts | Adds Detox offline/airplane-mode demo suite (currently does not actually disable connectivity). |
| tests/e2e/E2E_EXECUTION_REPORT.md | Documents claimed Detox execution results and environment notes. |
| tests/e2e/.detoxrc.js | Adds a local forwarding config to reuse the root Detox configuration. |
| src/sync/queue/OfflineQueueReader.ts | Migrates queue reading/claiming logic to SQLCipher sync_queue with transactional claiming and new helpers. |
| src/sync/queue/OfflineQueue.ts | Adds SQLCipher-backed queue write helpers (addItem, getAllItems). |
| src/sync/purge/PurgeManager.ts | Implements DONE-item purge for sync_queue. |
| src/sync/aws/SyncWorker.ts | Implements sequential queue drain with retry/backoff and DB-backed status transitions. |
| src/sync/aws/S3Uploader.ts | Adds real uploadToS3() via AWS SDK v3 alongside existing stub; introduces typed results. |
| src/storage/database/migrations/MigrationRunner.ts | Registers migration v3 for sync_queue. |
| src/storage/database/migrations/003_sync_queue.ts | Adds migration creating sync_queue table + status index. |
| package.json | Adds/adjusts Detox scripts and adds jest-junit; tweaks dependency ranges. |
| jest.config.js | Updates ignore patterns to exclude deploy/ from Jest scanning. |
| jest.config.e2e.js | Adds dedicated Jest config for Detox 20 runner integration. |
| deploy/aws/s3/lifecycle-rules.json | Adds S3 lifecycle rules JSON for transitions/expiration and multipart abort. |
| deploy/aws/s3/bucket-policy.json | Adds S3 bucket policy JSON example for Lambda write + transport constraints. |
| deploy/aws/lambda/sync-handler/package.json | Adds Lambda sync-handler package manifest and deploy script. |
| deploy/aws/lambda/sync-handler/index.js | Adds NDJSON batch receiver Lambda that writes to S3 with basic validation. |
| deploy/aws/lambda/authorizer/package.json | Adds Lambda authorizer package manifest for presigned URL generation. |
| deploy/aws/lambda/authorizer/index.js | Adds authorizer Lambda to generate presigned PUT URLs with placeholder token validation. |
| deploy/aws/cloudformation/template.yml | Adds CloudFormation template provisioning S3 bucket + Lambdas + IAM role. |
| android/gradle.properties | Increases Gradle memory, forces arm64-only ABI, and disables VisionCamera frame processors. |
| android/app/src/main/AndroidManifest.xml | Forces native lib extraction at install time. |
| android/app/build.gradle | Switches to legacy JNI packaging, resolves libcrypto conflicts, and adds OpenSSL dependency. |
| .detoxrc.js | Adds root Detox configuration with emulator + attached-device configurations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+11
to
+16
| import { | ||
| readNext, | ||
| markProcessing, | ||
| _inMemoryQueue, | ||
| type QueueItem, | ||
| } from '../../src/sync/queue/OfflineQueueReader'; |
Comment on lines
+19
to
+24
| import { | ||
| readNext, | ||
| _inMemoryQueue, | ||
| type QueueItem, | ||
| } from '../../src/sync/queue/OfflineQueueReader'; | ||
| import {uploadStub} from '../../src/sync/aws/S3Uploader'; |
Comment on lines
+169
to
+173
| `UPDATE sync_queue | ||
| SET status = 'PROCESSING', | ||
| updated_at = ? | ||
| WHERE queue_id = ? | ||
| AND status != 'PROCESSING';`, |
Comment on lines
+111
to
+129
| // Calculate backoff delay for next attempt. | ||
| const delayMs = getDelay(currentAttempt); | ||
| console.log( | ||
| `[SyncWorker] uploadWithRetry: waiting ${delayMs} ms before retry ` + | ||
| `(attempt ${currentAttempt + 1}).`, | ||
| ); | ||
|
|
||
| await sleep(delayMs); | ||
|
|
||
| // Increment attempt counter in DB and update local tracker. | ||
| currentAttempt = incrementAttempts(item.id); | ||
| if (currentAttempt < 0) { | ||
| // Item was not found in DB – bail. | ||
| console.error( | ||
| `[SyncWorker] uploadWithRetry: item "${item.id}" disappeared from DB.`, | ||
| ); | ||
| return 'FAILED'; | ||
| } | ||
| } |
Comment on lines
+89
to
+93
| /** S3 bucket name. Override via env/config in Phase 3. */ | ||
| const S3_BUCKET = 'nayan-offline-sync'; | ||
|
|
||
| /** S3 key prefix for queued sync records. */ | ||
| const S3_KEY_PREFIX = 'sync/events'; |
Comment on lines
+24
to
+31
| function validateDeviceToken(token) { | ||
| if (!token || !token.startsWith('Bearer ')) { | ||
| return false; | ||
| } | ||
| // NOTE: Replace with real JWT/HMAC validation in production. | ||
| const jwt = token.replace('Bearer ', ''); | ||
| return jwt.length > 16; | ||
| } |
Comment on lines
+82
to
+88
| const deviceId = event.queryStringParameters?.deviceId || 'unknown'; | ||
| const batchId = uuidv4(); | ||
| const objectKey = `attendance/${deviceId}/${batchId}.ndjson`; | ||
|
|
||
| // Conflict detection – check for duplicate batch key | ||
| const exists = await objectExists(objectKey); | ||
| if (exists) { |
| hermesEnabled=true | ||
|
|
||
| reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 | ||
| reactNativeArchitectures=arm64-v8a |
Comment on lines
+20
to
+21
| // Detox 20 supports launchArgs for toggling connectivity on emulator | ||
| launchArgs: {detoxEnableSynchronization: '0'}, |
Comment on lines
+19
to
+23
| | **GNG-01** | Face recognition accuracy | **> 95%** | 100-person trial on 3 physical devices; correct match count / total attempts | ☐ GO ☐ NO-GO | `tests/PHYSICAL_DEVICE_CHECKLIST.md` | | ||
| | **GNG-02** | End-to-end verification latency | **< 1 s** | Logcat timestamp delta: frame_captured → result_returned | ☐ GO ☐ NO-GO | Logcat + stopwatch | | ||
| | **GNG-03** | Release APK bundle size | **< 20 MB** | `node scripts/verify-model-bundle.js` + `du -sh` on APK | ☐ GO ☐ NO-GO | Script output below | | ||
| | **GNG-04** | `verifyChain()` tamper detection | **Must pass all scenarios** | Integration tests INT-TD-01 through INT-TD-08 | ✅ **GO** | `tests/INTEGRATION_TEST_REPORT.md` | | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Path: OfflineFaceAuth/.github/PULL_REQUEST_TEMPLATE.md
Purpose: PR template with checklist for code review: tests added, no new warnings, native build verified, member sign-off.