@burnt-labs/expo-satya-attest 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/PROVIDER_REGISTRY.md +271 -0
- package/PUBLISHING.md +291 -0
- package/README.md +374 -0
- package/android/build.gradle +37 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/expo/modules/satyaattest/SatyaAttestModule.kt +620 -0
- package/android/src/main/java/uniffi/satya_ffi/satya_ffi.kt +1423 -0
- package/android/src/main/jniLibs/arm64-v8a/libsatya_ffi.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libsatya_ffi.so +0 -0
- package/android/src/main/jniLibs/x86_64/libsatya_ffi.so +0 -0
- package/app.plugin.js +131 -0
- package/build/SatyaAttest.types.d.ts +200 -0
- package/build/SatyaAttest.types.d.ts.map +1 -0
- package/build/SatyaAttest.types.js +10 -0
- package/build/SatyaAttest.types.js.map +1 -0
- package/build/SatyaAttestModule.d.ts +29 -0
- package/build/SatyaAttestModule.d.ts.map +1 -0
- package/build/SatyaAttestModule.js +3 -0
- package/build/SatyaAttestModule.js.map +1 -0
- package/build/SatyaAttestModule.web.d.ts +14 -0
- package/build/SatyaAttestModule.web.d.ts.map +1 -0
- package/build/SatyaAttestModule.web.js +28 -0
- package/build/SatyaAttestModule.web.js.map +1 -0
- package/build/SatyaMobileClient.d.ts +37 -0
- package/build/SatyaMobileClient.d.ts.map +1 -0
- package/build/SatyaMobileClient.js +82 -0
- package/build/SatyaMobileClient.js.map +1 -0
- package/build/SatyaProviderAttestButton.d.ts +99 -0
- package/build/SatyaProviderAttestButton.d.ts.map +1 -0
- package/build/SatyaProviderAttestButton.js +801 -0
- package/build/SatyaProviderAttestButton.js.map +1 -0
- package/build/index.d.ts +13 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +16 -0
- package/build/index.js.map +1 -0
- package/build/providerPolicy.d.ts +10 -0
- package/build/providerPolicy.d.ts.map +1 -0
- package/build/providerPolicy.js +81 -0
- package/build/providerPolicy.js.map +1 -0
- package/build/providerRegistry.d.ts +17 -0
- package/build/providerRegistry.d.ts.map +1 -0
- package/build/providerRegistry.js +522 -0
- package/build/providerRegistry.js.map +1 -0
- package/build/providerWebview.d.ts +37 -0
- package/build/providerWebview.d.ts.map +1 -0
- package/build/providerWebview.js +524 -0
- package/build/providerWebview.js.map +1 -0
- package/build/providers.json +981 -0
- package/expo-module.config.json +9 -0
- package/ios/Frameworks/libsatya_ffi-rs.xcframework/Info.plist +29 -0
- package/ios/Frameworks/libsatya_ffi-rs.xcframework/ios-arm64/Headers/module.modulemap +7 -0
- package/ios/Frameworks/libsatya_ffi-rs.xcframework/ios-arm64/Headers/satya_ffi.swift +989 -0
- package/ios/Frameworks/libsatya_ffi-rs.xcframework/ios-arm64/Headers/satya_ffiFFI.h +585 -0
- package/ios/Frameworks/libsatya_ffi-rs.xcframework/ios-arm64/libsatya_ffi.a +0 -0
- package/ios/Generated/satya_ffi.swift +989 -0
- package/ios/SatyaAttest.podspec +27 -0
- package/ios/SatyaAttestModule.swift +932 -0
- package/package.json +83 -0
- package/scripts/build-rust-android.sh +51 -0
- package/scripts/build-rust-ios.sh +129 -0
- package/src/SatyaAttest.types.ts +239 -0
- package/src/SatyaAttestModule.ts +36 -0
- package/src/SatyaAttestModule.web.ts +36 -0
- package/src/SatyaMobileClient.ts +122 -0
- package/src/SatyaProviderAttestButton.tsx +1142 -0
- package/src/index.ts +48 -0
- package/src/providerPolicy.ts +122 -0
- package/src/providerRegistry.ts +683 -0
- package/src/providerWebview.ts +548 -0
- package/src/providers.json +981 -0
package/README.md
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# @burnt-labs/expo-satya-attest
|
|
2
|
+
|
|
3
|
+
Expo / React Native native module for SATYA mobile app attestation. The module uses
|
|
4
|
+
the Rust `satya-sdk` / `satya-ffi` pipeline for artifact construction and verifier
|
|
5
|
+
policy, while Swift and Kotlin provide platform-specific WebView capture, native HTTPS
|
|
6
|
+
replay, hardware-backed signing, and platform attestation evidence.
|
|
7
|
+
|
|
8
|
+
## Current Flow
|
|
9
|
+
|
|
10
|
+
The supported Expo flow is **certificate-pinned native replay**. Third-party apps can
|
|
11
|
+
use the SDK-owned button component for the full managed flow:
|
|
12
|
+
|
|
13
|
+
1. The app renders `SatyaProviderAttestButton` with a provider id and transport config.
|
|
14
|
+
2. The SDK refreshes SPKI pin policy from the verifier, falling back to registry pins.
|
|
15
|
+
3. The SDK opens an in-app `react-native-webview` modal for login and request discovery.
|
|
16
|
+
4. The SDK waits for a provider request that matches template `requestMatchRules`.
|
|
17
|
+
5. Swift/Kotlin replay the trusted template URL natively with shared WebView cookies.
|
|
18
|
+
6. The native client uses system trust without user roots and requires SPKI pins.
|
|
19
|
+
7. The Rust core emits a `native-pinned-observed` SATYA artifact.
|
|
20
|
+
8. The SDK verifies locally, optionally posts the artifact to `satya-verifier-service`,
|
|
21
|
+
and returns the result through `onComplete`.
|
|
22
|
+
|
|
23
|
+
The earlier mock and plain `webview-observed` modes are no longer exposed through the
|
|
24
|
+
high-level Expo client because they do not prove a provider response fetched through a
|
|
25
|
+
pinned native TLS connection.
|
|
26
|
+
|
|
27
|
+
## Native Trust Tiers
|
|
28
|
+
|
|
29
|
+
| Platform | Witness key | Platform evidence | Typical tier |
|
|
30
|
+
| ---------------- | ------------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------- |
|
|
31
|
+
| iOS device | Secure Enclave P-256 | App Attest assertion/attestation | `ios-app-attest-sep-bound` |
|
|
32
|
+
| iOS simulator | software P-256 | honest simulator fallback | `ios-simulator-dev` |
|
|
33
|
+
| Android device | Keystore EC, StrongBox when available | Play Integrity hook | `android-strongbox-play-integrity` / `android-keystore-play-integrity-no-strongbox` |
|
|
34
|
+
| Android emulator | software EC | honest emulator fallback | `android-emulator-dev` |
|
|
35
|
+
|
|
36
|
+
Artifacts are dev-notary signed by default. Production-grade verification requires
|
|
37
|
+
production notary keys, active templates, fresh revocation epochs, and pass-2 platform
|
|
38
|
+
verification where appropriate.
|
|
39
|
+
|
|
40
|
+
## Build The Rust Core
|
|
41
|
+
|
|
42
|
+
The generated native artifacts are gitignored:
|
|
43
|
+
|
|
44
|
+
- `ios/Frameworks/`
|
|
45
|
+
- `ios/Generated/`
|
|
46
|
+
- `android/src/main/jniLibs/`
|
|
47
|
+
- generated uniffi Swift/Kotlin glue
|
|
48
|
+
|
|
49
|
+
Build them from the workspace root before opening Xcode or Gradle:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# iOS XCFramework + Swift glue
|
|
53
|
+
platform_sdks/expo-satya-attest/scripts/build-rust-ios.sh
|
|
54
|
+
|
|
55
|
+
# Android .so files + Kotlin glue
|
|
56
|
+
# One-time prereqs: Android NDK, JDK 17, cargo-ndk, and Android Rust targets.
|
|
57
|
+
platform_sdks/expo-satya-attest/scripts/build-rust-android.sh
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
From the module directory, the same commands are available as:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm run build:native:ios
|
|
64
|
+
npm run build:native:android
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`build:native:ios` strips local/debug symbols from the XCFramework and publishes a
|
|
68
|
+
physical-device `arm64` iOS slice by default because the real App Attest flow does not
|
|
69
|
+
work on simulator. See [`PUBLISHING.md`](./PUBLISHING.md) for optional simulator fallback
|
|
70
|
+
builds and other binary-size knobs.
|
|
71
|
+
|
|
72
|
+
Build TypeScript after editing `src/*.ts` or `src/*.tsx`:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
cd platform_sdks/expo-satya-attest
|
|
76
|
+
npm install
|
|
77
|
+
npm run build
|
|
78
|
+
npm run lint
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The example app consumes the compiled `build/` directory, so restart Metro with
|
|
82
|
+
`--clear` after rebuilding the module.
|
|
83
|
+
|
|
84
|
+
## Provider Registry
|
|
85
|
+
|
|
86
|
+
Provider configs live in one SDK-owned JSON file: [`src/providers.json`](./src/providers.json).
|
|
87
|
+
The registry includes Kaggle, Deel, Gusto, Aadhaar, Uber, and Swiggy provider templates
|
|
88
|
+
ported from `mobile_tlsn_plugin`.
|
|
89
|
+
|
|
90
|
+
Useful exports:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import {
|
|
94
|
+
loadProviderRegistry,
|
|
95
|
+
listProviderRefs,
|
|
96
|
+
requireProviderTemplate,
|
|
97
|
+
SatyaProviderAttestButton,
|
|
98
|
+
validateProviderRegistry,
|
|
99
|
+
withProviderSpkiPins,
|
|
100
|
+
SatyaMobileClient,
|
|
101
|
+
} from '@burnt-labs/expo-satya-attest';
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Native replay requires at least one SPKI SHA-256 base64 pin at runtime. By default,
|
|
105
|
+
`SatyaProviderAttestButton` fetches
|
|
106
|
+
`GET /v1/providers/{providerId}/policy` from `transportConfig.notaryUrl` before opening
|
|
107
|
+
the WebView, validates that the returned provider id, host, template hash, and parser
|
|
108
|
+
hash match the selected template, and freezes those pins for the attestation run. If the
|
|
109
|
+
verifier is unavailable, it falls back to the SDK registry pins. Set
|
|
110
|
+
`providerPolicyRefresh="verifier-required"` to fail closed whenever the verifier policy
|
|
111
|
+
cannot be fetched, or `providerPolicyRefresh="template-only"` for offline demos.
|
|
112
|
+
|
|
113
|
+
## Installation Options
|
|
114
|
+
|
|
115
|
+
Every install path also needs the WebView peer dependency:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npx expo install react-native-webview
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Use npm for released apps:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npx expo install @burnt-labs/expo-satya-attest
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Use a local checkout while developing the SDK or testing unpublished changes:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
cd /path/to/tls-app-attest/platform_sdks/expo-satya-attest
|
|
131
|
+
npm install
|
|
132
|
+
npm run build
|
|
133
|
+
npm run check:native-artifacts
|
|
134
|
+
|
|
135
|
+
cd /path/to/your-expo-app
|
|
136
|
+
npm install /path/to/tls-app-attest/platform_sdks/expo-satya-attest
|
|
137
|
+
npx expo install react-native-webview
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Re-run `npm run build` in the SDK directory after TypeScript edits. Re-run the native
|
|
141
|
+
build scripts after Rust/UniFFI edits so the local package still contains
|
|
142
|
+
`ios/Generated`, `ios/Frameworks`, Android `jniLibs`, and generated Kotlin.
|
|
143
|
+
|
|
144
|
+
Use GitHub when you want a pinned unreleased version. The most reliable GitHub install
|
|
145
|
+
is a release tarball produced by `npm pack`, because it contains the same files npm
|
|
146
|
+
would publish:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npm install https://github.com/<owner>/<repo>/releases/download/expo-satya-attest-v0.1.0/burnt-labs-expo-satya-attest-0.1.0.tgz
|
|
150
|
+
npx expo install react-native-webview
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Installing from a Git ref also works when that ref has the SDK package at the repository
|
|
154
|
+
root, such as a dedicated SDK repo or a subtree/split branch:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm install github:<owner>/<sdk-repo>#v0.1.0
|
|
158
|
+
npm install git+https://github.com/<owner>/<sdk-repo>.git#v0.1.0
|
|
159
|
+
npx expo install react-native-webview
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Do not point npm at the monorepo root unless that Git ref is prepared so
|
|
163
|
+
`package.json`, `build/`, native artifacts, and Expo module files are at the root of the
|
|
164
|
+
Git package. npm does not install this monorepo's `platform_sdks/expo-satya-attest`
|
|
165
|
+
subdirectory directly from a normal GitHub URL.
|
|
166
|
+
|
|
167
|
+
After changing the install source, rebuild the native app:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npx expo prebuild --clean
|
|
171
|
+
npx expo run:ios --device
|
|
172
|
+
npx expo run:android
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Plug-And-Play API
|
|
176
|
+
|
|
177
|
+
Add the Expo config plugin as shown below, rebuild the native app, then render the
|
|
178
|
+
SDK-owned button:
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
import { SatyaProviderAttestButton } from '@burnt-labs/expo-satya-attest';
|
|
182
|
+
|
|
183
|
+
export function KaggleAttestation() {
|
|
184
|
+
return (
|
|
185
|
+
<SatyaProviderAttestButton
|
|
186
|
+
providerId="kaggle.current_user.v1"
|
|
187
|
+
providerPolicyRefresh="verifier-first"
|
|
188
|
+
transportConfig={{
|
|
189
|
+
notaryUrl: 'http://192.168.29.186:7047',
|
|
190
|
+
cloudProjectNumber: 0,
|
|
191
|
+
}}
|
|
192
|
+
verifyBackend
|
|
193
|
+
buttonLabel="Open Kaggle"
|
|
194
|
+
onComplete={(result) => {
|
|
195
|
+
console.log(result.raw);
|
|
196
|
+
console.log(result.verify);
|
|
197
|
+
console.log(result.backendVerify);
|
|
198
|
+
}}
|
|
199
|
+
onError={(error) => {
|
|
200
|
+
console.warn(error.message);
|
|
201
|
+
}}
|
|
202
|
+
/>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
When pressed, the component opens the provider WebView inside the same app, captures the
|
|
208
|
+
matching request, performs native replay with cookie sharing, verifies locally, posts to
|
|
209
|
+
the backend verifier when `verifyBackend` is set, and returns a
|
|
210
|
+
`SatyaProviderAttestationResult`.
|
|
211
|
+
|
|
212
|
+
Apps can customize the button label, modal title, WebView props, and callbacks. Apps
|
|
213
|
+
that use a custom provider allow-list can pass `providerTemplate` instead of
|
|
214
|
+
`providerId`. Explicit `spkiPins` are still supported for controlled tests and override
|
|
215
|
+
verifier/template policy refresh. The managed WebView uses provider `userAgent` settings
|
|
216
|
+
when present, otherwise it falls back to a mobile Chrome/Safari user agent like
|
|
217
|
+
`mobile_tlsn_plugin`;
|
|
218
|
+
pass `webViewUserAgent` to override it explicitly.
|
|
219
|
+
|
|
220
|
+
## Low-Level API
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
import {
|
|
224
|
+
SatyaMobileClient,
|
|
225
|
+
requireProviderTemplate,
|
|
226
|
+
withProviderSpkiPins,
|
|
227
|
+
} from '@burnt-labs/expo-satya-attest';
|
|
228
|
+
|
|
229
|
+
const providerTemplate = withProviderSpkiPins(requireProviderTemplate('kaggle.current_user.v1'), [
|
|
230
|
+
'KWQsjul7mJDk+i6fAisGLhWLd43FUs5ayVmkz5Y54DU=',
|
|
231
|
+
]);
|
|
232
|
+
|
|
233
|
+
const client = new SatyaMobileClient();
|
|
234
|
+
const { artifact, raw, verify } = await client.attestNativeReplay({
|
|
235
|
+
providerTemplate,
|
|
236
|
+
capturedRequest,
|
|
237
|
+
transportConfig: {
|
|
238
|
+
notaryUrl: 'http://127.0.0.1:7047',
|
|
239
|
+
cloudProjectNumber: 0,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
`capturedRequest` should come from the WebView interceptor and must match the selected
|
|
245
|
+
provider template. The returned `raw` string is the artifact JSON to post to
|
|
246
|
+
`POST /v1/artifacts/verify` on `satya-verifier-service`.
|
|
247
|
+
|
|
248
|
+
## Custom Provider Registries
|
|
249
|
+
|
|
250
|
+
Apps can keep provider templates outside the built-in SDK registry by passing
|
|
251
|
+
`providerRegistrySource` to the SDK-owned button:
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
<SatyaProviderAttestButton
|
|
255
|
+
providerId="acme.payroll.v1"
|
|
256
|
+
providerRegistrySource={{
|
|
257
|
+
url: 'https://example.com/.well-known/satya/providers.json',
|
|
258
|
+
timeoutMs: 10000,
|
|
259
|
+
maxBytes: 524288,
|
|
260
|
+
}}
|
|
261
|
+
providerPolicyRefresh="verifier-required"
|
|
262
|
+
transportConfig={{ notaryUrl: 'https://verifier.example.com' }}
|
|
263
|
+
/>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Or load it yourself for a custom selector:
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
const registry = await loadProviderRegistry({
|
|
270
|
+
url: 'https://example.com/.well-known/satya/providers.json',
|
|
271
|
+
});
|
|
272
|
+
const providers = listProviderRefs(registry);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Hosted registries are HTTPS-only by default, size/timeout bounded, and validated before
|
|
276
|
+
the WebView opens. See [`PROVIDER_REGISTRY.md`](./PROVIDER_REGISTRY.md) for the complete
|
|
277
|
+
JSON format, validation rules, and security review notes.
|
|
278
|
+
|
|
279
|
+
## Config Plugin
|
|
280
|
+
|
|
281
|
+
Add the plugin to inject App Attest entitlements and platform pinning config:
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"expo": {
|
|
286
|
+
"plugins": [
|
|
287
|
+
[
|
|
288
|
+
"@burnt-labs/expo-satya-attest",
|
|
289
|
+
{
|
|
290
|
+
"appAttestEnvironment": "development",
|
|
291
|
+
"pinnedProviders": [
|
|
292
|
+
{
|
|
293
|
+
"host": "www.kaggle.com",
|
|
294
|
+
"spkiSha256B64Pins": ["KWQsjul7mJDk+i6fAisGLhWLd43FUs5ayVmkz5Y54DU="]
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Use `development` for debug/TestFlight and `production` for App Store builds. iOS App
|
|
305
|
+
Attest requires a real device plus an App ID with the DeviceCheck/App Attest capability.
|
|
306
|
+
|
|
307
|
+
## Example App
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
cd platform_sdks/expo-satya-attest/expo-satya-attest-example
|
|
311
|
+
npm install --ignore-scripts
|
|
312
|
+
mkdir -p node_modules/@burnt-labs
|
|
313
|
+
ln -sfn ../.. node_modules/@burnt-labs/expo-satya-attest
|
|
314
|
+
npx expo run:ios --device
|
|
315
|
+
npx expo run:android
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
See [expo-satya-attest-example/README.md](./expo-satya-attest-example/README.md) for
|
|
319
|
+
device env setup and backend verifier commands.
|
|
320
|
+
|
|
321
|
+
## Verification Backend
|
|
322
|
+
|
|
323
|
+
Run the SATYA verifier service from the workspace root:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
cargo run -p satya-verifier-service
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
The service loads `crates/satya-verifier-service/.env`, which is prefilled locally with
|
|
330
|
+
provider-specific SPKI pins. For a physical device, set the Expo example's
|
|
331
|
+
`EXPO_PUBLIC_NOTARY_URL` to your laptop LAN URL, such as `http://192.168.29.186:7047`.
|
|
332
|
+
|
|
333
|
+
## Checks
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
cd platform_sdks/expo-satya-attest
|
|
337
|
+
npm run build
|
|
338
|
+
npm run lint
|
|
339
|
+
npm run release:check
|
|
340
|
+
|
|
341
|
+
cd expo-satya-attest-example
|
|
342
|
+
./node_modules/.bin/tsc --pretty false --noEmit
|
|
343
|
+
|
|
344
|
+
cd ../../..
|
|
345
|
+
cargo test -p satya-ffi native_replay_observed_nested_json_paths_verify
|
|
346
|
+
cargo test -p satya-verifier-service
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Publishing
|
|
350
|
+
|
|
351
|
+
The Expo SDK should publish to npm. The npm package must include the generated Android
|
|
352
|
+
`.so` files, generated UniFFI Kotlin/Swift glue, and iOS XCFramework so third-party apps
|
|
353
|
+
can install it without building Rust locally. See [`PUBLISHING.md`](./PUBLISHING.md) for
|
|
354
|
+
the release checklist, dry-run commands, binary-size guidance, and scoped-package naming
|
|
355
|
+
recommendations.
|
|
356
|
+
|
|
357
|
+
## Security Notes
|
|
358
|
+
|
|
359
|
+
- WebView response bytes are not attested. The WebView is only a login/request discovery
|
|
360
|
+
surface.
|
|
361
|
+
- Cookies are shared into native replay through platform cookie stores.
|
|
362
|
+
- Native replay blocks user roots and requires client-side SPKI pins so the replay
|
|
363
|
+
connection fails closed before producing an artifact.
|
|
364
|
+
- The SDK never learns production trust by fetching the provider's live certificate and
|
|
365
|
+
trusting it for the same run. Dynamic pins come from verifier policy, are validated
|
|
366
|
+
against the selected template, and are frozen before WebView capture starts.
|
|
367
|
+
- Backend verification independently re-derives trusted template hashes and pins from
|
|
368
|
+
backend config, not from the client artifact alone. Client pins protect the fetch;
|
|
369
|
+
backend pins protect acceptance.
|
|
370
|
+
- For production deployments, serve verifier policy over an authenticated channel
|
|
371
|
+
controlled by the verifier operator. Raw provider SPKI discovery is only suitable as a
|
|
372
|
+
manual/dev maintenance aid, not as automatic trust.
|
|
373
|
+
- Development artifacts remain dev-tier and should not be accepted by production
|
|
374
|
+
verifiers.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
plugins {
|
|
2
|
+
id 'com.android.library'
|
|
3
|
+
id 'expo-module-gradle-plugin'
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
group = 'expo.modules.satyaattest'
|
|
7
|
+
version = '0.1.0'
|
|
8
|
+
|
|
9
|
+
android {
|
|
10
|
+
namespace "expo.modules.satyaattest"
|
|
11
|
+
defaultConfig {
|
|
12
|
+
versionCode 1
|
|
13
|
+
versionName "0.1.0"
|
|
14
|
+
// StrongBox key attestation needs API 28+; basic Keystore attestation API 24+.
|
|
15
|
+
minSdkVersion 24
|
|
16
|
+
}
|
|
17
|
+
lintOptions {
|
|
18
|
+
abortOnError false
|
|
19
|
+
}
|
|
20
|
+
// Prebuilt per-ABI Rust libraries produced by scripts/build-rust-android.sh.
|
|
21
|
+
sourceSets {
|
|
22
|
+
main {
|
|
23
|
+
jniLibs.srcDirs += ['src/main/jniLibs']
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
dependencies {
|
|
29
|
+
// uniffi-generated Kotlin bindings load the native lib through JNA. The @aar
|
|
30
|
+
// classifier is mandatory on Android (the plain jar crashes at runtime).
|
|
31
|
+
implementation "net.java.dev.jna:jna:5.14.0@aar"
|
|
32
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
|
|
33
|
+
// Google Play Integrity (Android analog of iOS App Attest).
|
|
34
|
+
implementation "com.google.android.play:integrity:1.4.0"
|
|
35
|
+
// Native provider replay with certificate pinning and handshake capture.
|
|
36
|
+
implementation "com.squareup.okhttp3:okhttp:4.12.0"
|
|
37
|
+
}
|