* security fix
* more security fixes
* fixes
* pr feedback
* Restore remote URL loading in native-shell-ios and native-shell-android
Remove bundled-asset-only loading and SHA-256 integrity checks from both
native shell packages. WebViews now load directly from the remote URL
(default: https://self-app-alpha.vercel.app) over HTTPS, matching the
pattern already implemented in kmp-sdk and self-sdk-swift.
Also fixes ObjC selector mismatch in self-sdk-swift WebViewProviderImpl
for configureRemoteLoading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Restore remote URL loading in kmp-sdk and self-sdk-swift
Remove bundled-asset-only loading from kmp-sdk AndroidWebViewHost and
self-sdk-swift WebViewProviderImpl. Both now load directly from the
remote URL (default: https://self-app-alpha.vercel.app) over HTTPS.
Adds remoteWebAppBaseUrl to SelfSdkConfig and pipes it through
IosWebViewHost via the new configureRemoteLoading protocol method.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* coderabbit comments
* lint
* coderabbit comments
---------
Co-authored-by: seshanthS <seshanth@protonmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* test: ofac updating tests
* feat: add registry deployment info
* chore: add gitignore for generated files
* feat: add kyc documents to upgrade scripts
* docs: update upgrade script readme for kyc
* feat: IdentityRegistryKyc v1.1.0 deployed on Celo-sepolia
Add TEE-attested OFAC root updates via updateOfacRootsWithProof
- Implementation: 0x530eEA7E5b286108926B05510491560c4bAE018e
- Adds updateOfacRootsWithProof() for ZK-verified OFAC root updates
- New errors: InvalidRootsHash, InvalidRootsCount
- New event: OfacRootsUpdatedWithProof
* feat: add OFAC rolling root window to all 4 registries
Add previousRoot storage variables to all identity registries so that
checkOfacRoots accepts both the current and previous root for each OFAC tree. This prevents verification failures for users mid-proof when roots are updated on-chain between proof generation and on-chain verification.
- Passport: 3 prev roots (passportNo, nameAndDob, nameAndYob)
- KYC, ID Card, Aadhaar: 2 prev roots each (nameAndDob, nameAndYob)
- KYC updateOfacRootsWithProof also rotates previous roots
- Added getPrev* getter functions on all registries
- Storage appended at end of each storage contract (UUPS-safe)
- 17 new tests covering all registries (window=1 acceptance/rejection)
* feat: deploy IdentityRegistryKyc v1.2.0 to Celo Sepolia
Add rolling OFAC root window: store previous roots alongside current, accept either in checkOfacRoots for graceful mid-verification transitions.
New impl: 0x6E2889Bc9baa6F53bDdf4843675155811F0AAAEd
Proxy: 0x90e907E4AaB6e9bcFB94997Af4A097e8CAadBdf3
Pending Safe multisig execution for proxy upgrade.
* feat: add TEE-attested OFAC root updates to Aadhaar, IdCard, and Passport registries
Extend updateOfacRootsWithProof() to the remaining 3 identity registries, matching the pattern already deployed on the KYC registry (v1.1.0).
- Add GCP JWT verifier, PCR0Manager, TEE address, and root CA pubkey hash storage to each registry
- Add initializeOfacProof() reinitializer for upgrade path
- Add onlyTEE modifier and updateOfacRootsWithProof() with Groth16 proof verification, TEE attestation validation, timestamp checks, and global roots hash commitment verification
- Rolling window behavior preserved: previous roots saved before overwrite
- Admin functions for updating TEE infrastructure (SECURITY_ROLE gated)
- Bumps all 3 registries to v1.3.0
* refactor: simplify updateOfacRootsWithProof to use per-registry roots hash as nonce
* fix: address CodeRabbit review comments on OFAC proof upgrade
- Add onlyProxy + onlyRole(DEFAULT_ADMIN_ROLE) guard to initializeOfacProof()
on Passport, Aadhaar, and IdCard registries to prevent front-running during
the window between upgradeToAndCall and the separate initializer call
- Fix checkOfacRoots() across all 4 registries to use atomic snapshot comparison
instead of per-root matching — prevents accepting Frankenstein pairs like
(new DOB root, old YOB root) that were never attested together
- Add IdentityRegistryKycImplV1 to PoseidonT3 linking branch in prepare.ts so
upgrade:prepare works correctly for KYC
- Add prev* slot assertions and mixed-pair rejection test to ofacUpgradePath.test.ts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add view getters, fix initializeOfacProof guard, add upgrade scripts
- Add getGcpJwtVerifier() and getPcr0Manager() getters to KYC and Aadhaar
- Fix initializeOfacProof guard: SECURITY_ROLE instead of DEFAULT_ADMIN_ROLE
(DEFAULT_ADMIN_ROLE is never granted in governance setup)
- Add Ignition upgrade scripts for KYC and Aadhaar registries
- Comment out registry deploy in deployKycRegistry (verifier-only redeploy)
- Update deployed_addresses.json with sepolia upgrade artifacts
- Bump KYC to v1.2.1, Aadhaar to v1.3.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: addresses and error selectors
* style: format registry contracts and upgrade scripts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: formatting
* fix: error selectors
* fix: error selectors
* fix: error selectors
---------
Co-authored-by: Evi Nova <tranquil_flow@protonmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add remote webview integrity checks
* fixes
* feedback
* update tests; fix pipelines
* fix ci
* feat(webview): add subresource integrity (SRI) to build output
The SHA-256 remote integrity check only covers the entry HTML document.
Sub-resources (JS, CSS) loaded by that HTML were fetched without
integrity verification, allowing a compromised CDN to swap bundles.
Add a custom Vite plugin that injects SRI sha384 hashes into all
script and link tags in the built index.html. The browser natively
enforces these hashes, blocking any tampered sub-resources.
Includes tests verifying integrity attributes are present and that
hashes match the actual file contents on disk.
---------
Co-authored-by: Tranquil-Flow <tranquil_flow@protonmail.com>
* stitch tunnelflow screens
* save wip formatting
* add failure flow
* stub account recovery
* add tests
* add spec wv-17
* prep for review
* serialize
* fixes
* fix bug
* fix dev building
* fix: close Didit modal on completion, show KycPendingScreen while waiting (#1900)
- Close Didit SDK modal immediately when onComplete fires
- Show Euclid KycPendingScreen with animation while Socket.IO waits for TEE attestation
- Replaces generic spinner for the 'In Review' waiting state
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* navigate to disclose step on restore
* skip disclose confirmation screen
* Update Recovery flow
* Navigate to account recovery if TEE rejects it as already registered
* Navigate to disclose directly if the selected document is registered
* SELF-2348: Load webapp from url
* update sdk-test-app
* fix result from sdk
* fixes?
* fix build issue
* fix install pipeline
* carry pr feedback. fix formatting
---------
Co-authored-by: Justin Hernandez <justin.hernandez@self.xyz>
Co-authored-by: Nesopie <87437291+Nesopie@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: store KYC document in keychain after receiving TEE attestation
Build a KycData document from the attestation (signature, applicantInfo,
pubkey) and persist it via storePassportData → keychain-backed adapter.
This makes the document available for the proving machine.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: KYC document mock is always false
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* provingmachine flow with mock passport
* add yarn.lock
* Fix coderabbit comments
* lint
* update coderabbit comments
* coderabbit comments
* Merge branch 'dev' into feat/didit-keychain-storage
* fix: reorder KYC constants declarations and fix formatting
Constants were declared out of order causing "used before declaration"
TS errors. Reordered to match the 295-byte layout sequentially.
Also ran prettier on common package.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix proving phase handling and add delete catalog debug button
- TunnelProvingScreen: use `phase !== 'disclose'` to handle completion
for both passport (dsc→register→disclose) and kyc/aadhaar (register→disclose)
- KeychainDebugScreen: add Delete Catalog button to clear all documents
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* coderabbit comments
---------
Co-authored-by: ayman <aymanshaik1015@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use raw bytes for KYC register circuit inputs instead of deserialize+reserialize
The deserialize→reserialize path strips the namespace prefix from
id_type, producing different bytes than what the TEE signed. This
causes EdDSA signature verification to fail in the circuit.
Use raw base64-decoded bytes directly, matching the TEE's signed data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use raw bytes for KYC register circuit inputs in common and new-common
The deserialize→reserialize path strips the namespace prefix from
id_type (\x05didit), producing different bytes than what the TEE
signed. This causes EdDSA signature verification to fail in the
register_kyc circuit.
Use raw base64-decoded bytes directly in both common/ and new-common/.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use raw bytes for KYC disclose circuit inputs
Same issue as register — .toString('utf-8') corrupts bytes >= 128,
causing Num2Bits assertion failures in vc_and_disclose_kyc circuit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use raw bytes for KYC disclose circuit inputs in new-common
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove dev functions from KYC registry, add upgrade module, clean up debug logs
- Remove devRemoveNullifier and devResetTree (no longer needed)
- Add upgradeKycRegistry ignition module
- Update deployed_addresses.json with new KYC registry proxy
- Remove debug logging from provingMachine
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace unused teeUrl with environment ("prod"/"staging") for endpoint selection. The webview never consumed teeUrl — the proving machine resolves TEE URLs internally from the circuit DNS mapping API based on environment.
Add version (default 1) for config protocol versioning. Add optional verification config fields: scope, disclosures, appName, appEndpoint, resultType — needed for the tunnel flow to render the proof request UI correctly. The webview already parsed these from URL params; the native shells just weren't sending them.
Update webview to parse environment and version from URL params with defensive defaults. Update both test apps to use the new config shape.
* feat: replace Sumsub with Didit JS SDK in webview-app
- Add @didit-protocol/sdk-web, remove @sumsub/websdk
- Create diditProvider.ts with session creation + SDK launch
- Update ProviderLaunchScreen to use Didit embedded mode
- Delete sumsubProvider.ts and sumsub-websdk.d.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add Socket.IO attestation flow to webview KYC
After Didit JS SDK completes, connect Socket.IO to the TEE,
subscribe by sessionId, and wait for signed KYC data (attestation).
Emit ack_success for session cleanup. Attach attestation to the
provider result before navigating to the result screen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: update TEE URL to kyc.self.xyz, update SDK test app README for Didit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: only route KYC (Other IDs) to Didit provider, others to Coming Soon
Passport, ID card, and Aadhaar require NFC/MRZ scanning which isn't
available in the WebView. Only "Other IDs" goes through the Didit
JS SDK flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: Didit SDK full-width rendering and KYC routing
- Wire onNotListedPress to launch Didit for "View other supported IDs"
- Remove verificationId gate from ProviderLaunchScreen
- Switch to modal mode with CSS overrides for full-screen on mobile
- Force .shadow-card to 100% width/height in WebView context
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add camera permissions and file upload to Android WebView
Add WebChromeClient to AndroidWebViewHost:
- onPermissionRequest: auto-grants camera for Didit SDK
- onShowFileChooser: opens system file picker for document upload
- SelfVerificationActivity handles file chooser result callback
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: gitignore Gradle build artifacts for native-shell-android
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add runtime camera permission and CAMERA manifest declaration
- Add CAMERA permission to sdk-test-app AndroidManifest.xml
- Request runtime camera permission in onPermissionRequest before granting
- Handle permission result in SelfVerificationActivity
- Store pending PermissionRequest for async grant/deny after user response
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix ios camera
* fix: address CodeRabbit review findings
- Replace ngrok URL with kyc.self.xyz in Android and iOS test apps
- Fix file chooser hang when context is not an Activity
- Move NSCameraUsageDescription to project.yml (survives xcodegen regen)
- Delete manual Info.plist that would be overwritten
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: replace ngrok URL with kyc.self.xyz in diditProvider and diditAttestation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: explicitly disable Didit SDK debug logging
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: webview lint
* fix: validate origin and handle audio permission in WebView permission grants
- Deny permission requests from untrusted origins
- Deny instead of grant when context is not an Activity
- Handle RECORD_AUDIO alongside CAMERA for liveness checks
- Add RECORD_AUDIO to AndroidManifest.xml
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: seshanthS <seshanth@protonmail.com>
* feat: add iOS native shell package (NSL-02)
Plain Swift implementation of the WebView host with bridge handlers
for secure storage (Keychain), crypto (EC P-256), and lifecycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Android native shell package (NSL-01)
Plain Kotlin implementation of the WebView host with bridge handlers
for secure storage (EncryptedSharedPreferences), crypto (Android Keystore
EC P-256), and lifecycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: integrate Sumsub Web SDK into ProviderLaunchScreen (WV-05)
Rewrites ProviderLaunchScreen to launch Sumsub Web SDK, adds KYC
provider types, result normalization, and a ProviderResultScreen
for displaying verification outcomes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update spec status for NSL-01, NSL-02, WV-05 to in-progress
All three items are code-complete but need integration testing
before marking done.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add build-pipeline workstream specs, update NSL-03 and BP-01 status
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add WebView bundle build pipeline (BP-01)
Build script copies webview-app dist into both native shell asset
directories. Gradle preBuild validation fails fast when bundle is
missing. Root package.json gets build:sdk-* scripts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add SDK test apps for Android and iOS (NSL-03)
Minimal test apps to exercise native shells end-to-end:
- Android: Jetpack Compose app using SelfSdk.launch() via composite build
- iOS: SwiftUI app using SelfSdk.createViewController() via local SPM dep
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* update lockfile
* fix: address CodeRabbit PR review findings for native shells
- Fix iOS double callback: add hasEmittedResult flag to LifecycleHandler
so dismiss() won't fire onCancelled after onResult already emitted
- Fix Android error result codes: use RESULT_FIRST_USER for failed
verifications instead of always RESULT_OK; add dedicated handler in
SelfSdk.handleResult
- Fix iOS production query params: append params to file URL via
URLComponents so WebView receives teeUrl/verificationId/userId
- Fix build:sdk-ios false-green: chain swift build after bundle script
- Add expectedRequestCode param to handleResult for flexibility
- Upgrade security-crypto 1.1.0-alpha06 → 1.1.0 stable
- Improve callback type safety: onSuccess takes raw JSON string,
onFailure takes SelfSdkException instead of generic Exception
- Add requireBiometric intent comments to both SecureStorageHandlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address remaining CodeRabbit PR review findings (round 2)
- iOS BridgeResponse: add requestId/success fields, rename result→data to match JS bridge contract
- iOS test app: fix callback deallocation with Coordinator pattern
- ProviderLaunchScreen: fail closed on missing verificationId, fix retry via retryCount state
- ProviderResultScreen: guard unknown status with fallback to error config
- build-webview-bundle.sh: validate index.html before deleting targets
- Package.swift: fix SPM resource path with target path/sources
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>