Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,19 @@ NEXT_PUBLIC_X_PIXEL_ID=r9lkr
# Format: Long OAuth 2.0 Bearer token (e.g., AAAAAAAAAAAAAAAAAAAAAMLheAAAAAAA0%2BuSeid...)
# IMPORTANT: This is different from your main X API token - it's specifically for Conversions API
X_CONVERSIONS_API_TOKEN=your_x_api_token_here

# Native store billing (server-only). See docs/mobile-billing.md before enabling.
MOBILE_BILLING_ENABLED=false
MOBILE_BILLING_TOKEN_KEY=
APPLE_IAP_ISSUER_ID=
APPLE_IAP_KEY_ID=
APPLE_IAP_PRIVATE_KEY=
APPLE_APP_ID=
APPLE_STORE_ENVIRONMENT=Production
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON=
GOOGLE_PLAY_ALLOW_TEST_PURCHASES=false
GOOGLE_RTDN_AUDIENCE=
GOOGLE_RTDN_SERVICE_ACCOUNT_EMAIL=

# Ciphertext-only mobile sync: run npm run vault:migrate before enabling.
VAULT_SYNC_ENABLED=false
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
apps/android/gradlew.bat text eol=crlf
81 changes: 81 additions & 0 deletions .github/workflows/native-clients.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Native clients

on:
pull_request:
workflow_dispatch:

jobs:
android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21
- uses: android-actions/setup-android@v3
with:
packages: platform-tools
- run: sdkmanager 'platforms;android-35' 'build-tools;35.0.0' 'ndk;27.2.12479018'
- run: python3 scripts/prepare-public-sample.py
- run: node scripts/build-native.mjs android arm64-v8a
- run: apps/android/gradlew -p apps/android assembleDebug testDebugUnitTest lintDebug --no-daemon
- uses: actions/upload-artifact@v7
with:
name: explorer-android-debug
path: apps/android/app/build/outputs/apk/debug/app-debug.apk
- run: node scripts/build-native.mjs android x86_64
- name: Enable emulator KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 35
arch: x86_64
script: apps/android/gradlew -p apps/android -PexplorerAbis=x86_64 connectedDebugAndroidTest --no-daemon

- uses: actions/upload-artifact@v7
if: always()
with:
name: explorer-android-test-results
path: |
apps/android/app/build/reports/androidTests
apps/android/app/build/outputs/androidTest-results

ios:
runs-on: macos-15
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
- run: brew install xcodegen
- run: python3 scripts/prepare-public-sample.py
- run: node scripts/build-native.mjs ios simulator
- name: Run native binding tests in iOS Simulator
shell: bash
run: |
simulator_id=$(xcrun simctl list devices available -j | python3 -c 'import json,sys; d=json.load(sys.stdin); print(next(v["udid"] for devices in d["devices"].values() for v in devices if v["name"].startswith("iPhone")))')
xcodebuild -resultBundlePath apps/ios/ExplorerTests.xcresult -project apps/ios/Explorer.xcodeproj -scheme Explorer -destination "platform=iOS Simulator,id=$simulator_id" -derivedDataPath apps/ios/build test CODE_SIGNING_ALLOWED=NO

- name: Export iOS visual snapshots
if: always()
run: |
if [ -d apps/ios/ExplorerTests.xcresult ]; then
xcrun xcresulttool export attachments --path apps/ios/ExplorerTests.xcresult --output-path apps/ios/test-attachments
fi
- uses: actions/upload-artifact@v7
if: always()
with:
name: explorer-ios-visual-snapshots
path: apps/ios/test-attachments
- uses: actions/upload-artifact@v7
if: always()
with:
name: explorer-ios-test-results
path: apps/ios/ExplorerTests.xcresult
63 changes: 63 additions & 0 deletions .github/workflows/pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ jobs:
build:
runs-on: ubuntu-latest

services:
billing-postgres:
image: postgres:17
env:
POSTGRES_USER: explorer
POSTGRES_PASSWORD: billing-test-only
POSTGRES_DB: billing_test
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U explorer -d billing_test"
--health-interval 5s --health-timeout 5s --health-retries 10

strategy:
matrix:
node-version: [24.x]
Expand All @@ -27,6 +40,26 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Verify store billing and atomic purchase ledger
run: |
node scripts/migrate-mobile-billing.mjs
npm run test:billing
npm run vault:migrate
npm run test:vault-sync
env:
POSTGRES_DB: postgresql://explorer:billing-test-only@127.0.0.1:5432/billing_test
BILLING_DB_TEST: 'true'
VAULT_DB_TEST: 'true'

- name: Install shared core toolchain
run: rustup show active-toolchain

- name: Test Rust and WASM contracts
run: |
npm run core:test
npm test
npm run test:run-all

- name: Run linter
run: npm run lint

Expand All @@ -38,6 +71,36 @@ jobs:
env:
NODE_ENV: production

- name: Prepare full public 23andMe sample and browser
run: |
npm run test:public-sample:prepare
npx playwright install --with-deps chromium

- name: Verify public sample import, scores, export and portable vault in Chromium
run: |
node node_modules/next/dist/bin/next start > /tmp/explorer-public-sample-server.log 2>&1 &
app_pid=$!
trap 'kill "$app_pid"' EXIT
node --input-type=module <<'JS'
let ready=false;
for(let attempt=0;attempt<60;attempt++) {
try { if((await fetch('http://127.0.0.1:3000')).ok){ready=true;break;} } catch {}
await new Promise(resolve=>setTimeout(resolve,500));
}
if(!ready)throw new Error('Production server did not start');
JS
npm run test:public-sample:web

- name: Upload public sample browser evidence
uses: actions/upload-artifact@v7
with:
name: public-sample-browser-evidence
include-hidden-files: true
path: |
.test-data/public-sample/*.png
.test-data/public-sample/web-results.tsv
retention-days: 7

- name: Upload build artifacts
if: matrix.node-version == '24.x'
uses: actions/upload-artifact@v7
Expand Down
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,25 @@ yarn-error.log*
/CLAUDE.md
/scripts/ga-performance.env
/.junie/

# Shared Rust and generated native bindings
/target/
/lib/generated/
/apps/android/.gradle/
/apps/android/local.properties
/apps/android/**/build/
/apps/android/app/src/main/jniLibs/
/apps/android/app/src/main/java/com/monadicdna/explorer/core/
/apps/ios/Generated/
/apps/ios/build/
/apps/ios/*.xcodeproj/
/apps/ios/*.xcworkspace/
/.test-data/
/apps/ios/TestData/
/apps/android/app/src/androidTest/assets/public-sample/

# Kotlin compiler workspace cache
apps/android/.kotlin/

apps/ios/*.xcresult/
apps/ios/test-attachments/
Loading
Loading