@burnt-labs/expo-satya-attest 0.2.4 → 0.3.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/PROVIDER_CONFIG.md +159 -42
  3. package/README.md +33 -15
  4. package/android/build.gradle +2 -2
  5. package/android/src/main/java/expo/modules/satyaattest/SatyaAttestModule.kt +26 -7
  6. package/build/SatyaAttest.types.d.ts +34 -17
  7. package/build/SatyaAttest.types.d.ts.map +1 -1
  8. package/build/SatyaAttest.types.js.map +1 -1
  9. package/build/SatyaMobileClient.d.ts.map +1 -1
  10. package/build/SatyaMobileClient.js +16 -0
  11. package/build/SatyaMobileClient.js.map +1 -1
  12. package/build/SatyaProviderAttestButton.d.ts +24 -1
  13. package/build/SatyaProviderAttestButton.d.ts.map +1 -1
  14. package/build/SatyaProviderAttestButton.js +409 -186
  15. package/build/SatyaProviderAttestButton.js.map +1 -1
  16. package/build/debugLog.d.ts +69 -0
  17. package/build/debugLog.d.ts.map +1 -0
  18. package/build/debugLog.js +203 -0
  19. package/build/debugLog.js.map +1 -0
  20. package/build/index.d.ts +4 -2
  21. package/build/index.d.ts.map +1 -1
  22. package/build/index.js +2 -1
  23. package/build/index.js.map +1 -1
  24. package/build/providerRegistry.d.ts.map +1 -1
  25. package/build/providerRegistry.js +140 -66
  26. package/build/providerRegistry.js.map +1 -1
  27. package/build/providerWebview.d.ts +14 -5
  28. package/build/providerWebview.d.ts.map +1 -1
  29. package/build/providerWebview.js +63 -6
  30. package/build/providerWebview.js.map +1 -1
  31. package/build/providers.json +272 -89
  32. package/ios/Frameworks/libsatya_ffi-rs.xcframework/ios-arm64/libsatya_ffi.a +0 -0
  33. package/ios/Frameworks/libsatya_ffi-rs.xcframework/ios-arm64_x86_64-simulator/libsatya_ffi.a +0 -0
  34. package/ios/SatyaAttest.podspec +1 -1
  35. package/ios/SatyaAttestModule.swift +19 -2
  36. package/package.json +3 -2
  37. package/src/SatyaAttest.types.ts +35 -17
  38. package/src/SatyaMobileClient.ts +16 -0
  39. package/src/SatyaProviderAttestButton.tsx +590 -281
  40. package/src/debugLog.ts +258 -0
  41. package/src/index.ts +16 -0
  42. package/src/providerRegistry.ts +166 -71
  43. package/src/providerWebview.ts +69 -6
  44. package/src/providers.json +272 -89
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 - 2026-06-14
4
+
5
+ - Reworked the managed provider WebView into a polished, native-feeling surface: removed the browser-style chrome (address/host bar, lock icon, reload, and close buttons) so the flow reads as a screen of the host app rather than an in-app browser.
6
+ - Exiting the flow now uses the device's own back affordance: the hardware/gesture back button on Android, and a left-edge swipe-back gesture on iOS (which has no hardware back button). Either one dismisses an open OAuth popup first, otherwise closes the WebView — no on-screen close/back buttons.
7
+ - Fixed WebView clipping into the notch / status bar and the home indicator / on-screen navigation bar by applying correct top, bottom, and side safe-area insets across devices. Adds `react-native-safe-area-context` as a required peer dependency (install it alongside `react-native-webview`).
8
+ - Added an optional `theme` prop (`surfaceColor`, `onSurfaceColor`, `mutedColor`, `accentColor`, `statusBarStyle`) so the WebView surface can match the host app's brand. Pass `modalTitle=""` to hide the header title.
9
+
3
10
  ## 0.2.2 - 2026-06-11
4
11
 
5
12
  - Fixed provider WebView login flows that could continuously refresh while the user was still on a login or SSO host.
@@ -22,6 +22,34 @@ provider shape inside a registry wrapper:
22
22
  The registry-level `schemaVersion` is optional in the SDK loader. Each provider entry
23
23
  must still carry its own `schemaVersion`.
24
24
 
25
+ The current built-in provider entries use this top-level shape:
26
+
27
+ ```jsonc
28
+ {
29
+ "schemaVersion": "1.0.0",
30
+ "providerId": "provider.proof.v1",
31
+ "name": "Provider",
32
+ "login": { "url": "https://provider.example/login" },
33
+ "endpoints": [],
34
+ "tlsIdentityPolicy": {
35
+ "expectedSni": "provider.example",
36
+ "spkiSha256B64Pins": []
37
+ },
38
+ "templateGovernance": {
39
+ "templateHash": "dev-provider-proof-v1-template",
40
+ "parserHash": "parser-sha256:<64 hex chars>"
41
+ }
42
+ }
43
+ ```
44
+
45
+ The endpoint shape is also explicit. The supported endpoint keys are `id`, `url`,
46
+ `method`, `headers`, `responseType`, `requestMatchRules`, `revealRules`, optional
47
+ `capture`, optional `replayCapturedUrl`, and optional `htmlCaptureBodyPattern`.
48
+ Endpoint active-fetch/readiness settings must be grouped under endpoint `capture`.
49
+ Endpoint `injection` and old flat endpoint fields such as `triggerFromInjection`, `injectionHeaders`,
50
+ `injectionLandingUrl`, `injectionPollMs`, `injectionMaxAttempts`, and flat
51
+ `requireLoginSignal` are invalid.
52
+
25
53
  ## Minimal Provider
26
54
 
27
55
  ```json
@@ -80,15 +108,15 @@ Required provider fields:
80
108
 
81
109
  | Field | Description |
82
110
  |---|---|
83
- | `schemaVersion` | Provider schema version string. The built-in registry currently uses `1.0.0`. |
84
- | `providerId` | Stable provider id, for example `kaggle.current_user.v1`. It must be unique within a registry. |
85
- | `name` | User-facing provider name. Legacy `label` and `displayName` are accepted, but new configs should use `name`. |
86
- | `login.url` | HTTPS page opened in the managed WebView for login and request discovery. |
87
- | `endpoints` | Non-empty array of proof endpoints. If no endpoint id is selected, the SDK uses the first endpoint. |
88
- | `tlsIdentityPolicy.expectedSni` | Expected HTTPS host/SNI. Every endpoint URL must use this same host. |
89
- | `tlsIdentityPolicy.spkiSha256B64Pins` | Public SPKI SHA-256 pins for native replay. Built-in providers and device E2E should keep this non-empty. |
90
- | `templateGovernance.templateHash` | Template identity accepted by the verifier. |
91
- | `templateGovernance.parserHash` | Parser identity derived from provider id, endpoint ids, response types, and reveal rules. |
111
+ | `schemaVersion` | Provider schema version string. The built-in registry currently uses `1.0.0`. This is separate from the optional registry wrapper `schemaVersion`. |
112
+ | `providerId` | Stable provider id, for example `kaggle.current_user.v1`. It must be unique within a registry and should include a proof name plus version suffix so verifier policy can pin it safely. |
113
+ | `name` | User-facing provider name shown in selectors and UI surfaces. New configs should use `name`; legacy `label` and `displayName` are normalized for compatibility but are not needed for new providers. |
114
+ | `login.url` | HTTPS page opened in the managed WebView. Pick the provider's normal sign-in or account page, not the raw API URL, so cookies are established in the WebView before capture/replay. |
115
+ | `endpoints` | Non-empty array of proof endpoints. Each endpoint describes one replayable request and its reveal policy. If no endpoint id is selected, the SDK uses the first endpoint. |
116
+ | `tlsIdentityPolicy.expectedSni` | Expected HTTPS host/SNI for native replay. Every endpoint URL must use this same host, and captured dynamic URLs are constrained to this host before replay. |
117
+ | `tlsIdentityPolicy.spkiSha256B64Pins` | Base64 SHA-256 SPKI pins for the provider TLS certificate chain. Native replay requires at least one pin at runtime and fails closed when the replay connection does not match policy. |
118
+ | `templateGovernance.templateHash` | Template identity accepted by the verifier. This ties the provider id, replay target, and policy version to verifier-side allowlists. |
119
+ | `templateGovernance.parserHash` | Parser identity derived from provider id, endpoint ids, response types, and reveal rules. Run `npm run test:providers` after editing reveal policy; the test prints the expected value when stale. |
92
120
 
93
121
  Optional provider fields:
94
122
 
@@ -99,15 +127,15 @@ Optional provider fields:
99
127
  | `label`, `displayName` | Legacy display fields. The loader normalizes them to `name`/`label`/`displayName`. |
100
128
  | `version` | Optional version string. If omitted, the SDK infers it from the final `.vN` segment of `providerId`. |
101
129
  | `auth` | Optional object for provider-auth metadata. The current SDK preserves it but does not interpret it in the managed flow. |
102
- | `injection` | Optional JavaScript string, array of strings, or `null`. Runs in the managed WebView on every main and popup page alongside the SDK interceptor. |
130
+ | `injection` | Optional provider-level JavaScript string, array of strings, or `null`. Runs in the managed WebView on every main and popup page alongside the SDK interceptor. Use it for provider-specific page navigation, login readiness checks, popup handoff, or posting `__satyaReady`. This is different from endpoint-level `capture`, which configures active fetch/readiness for one endpoint. |
103
131
  | `target` | Legacy compatibility object. If present, it must be `{ "scheme": "https", "host": expectedSni, "port": 443 }`. The loader generates this when omitted. |
104
132
  | `webLogin` | Legacy compatibility object. `login.url` is preferred. If only `webLogin.startUrl` is present, the loader maps it to `login.url`. |
105
- | `userAgent` | Optional `{ "ios": string | null, "android": string | null }`. Used by the managed WebView when no explicit `webViewUserAgent` prop is supplied. |
106
- | `tlsIdentityPolicy.allowedAlpn` | Optional ALPN metadata. Native replay measures negotiated ALPN and verifier policy checks the artifact. |
133
+ | `userAgent` | Optional `{ "ios": string | null, "android": string | null }`. Used by the managed WebView when no explicit `webViewUserAgent` prop is supplied. Include it when a provider serves different pages/APIs to mobile and desktop agents and the replay must match the WebView. |
134
+ | `tlsIdentityPolicy.allowedAlpn` | Optional ALPN metadata. Native replay measures negotiated ALPN and verifier policy can check the artifact. |
107
135
  | `tlsIdentityPolicy.spkiSha256Hex` | Legacy/pass-through metadata. Prefer `spkiSha256B64Pins`. |
108
136
  | `tlsIdentityPolicy.tlsTrustStorePolicy` | Optional, but if present it must be `web-pki-os-roots-no-user-roots`. The loader fills this value when omitted. |
109
137
  | `tlsIdentityPolicy.userRootsAllowed` | Optional, but if present it must be `false`. The loader fills `false` when omitted. |
110
- | `tlsIdentityPolicy.redirectPolicyId` | Optional redirect-policy metadata. Native replay currently blocks redirects. |
138
+ | `tlsIdentityPolicy.redirectPolicyId` | Optional redirect-policy metadata. Native replay currently blocks redirects, so do not rely on redirects for proof requests. |
111
139
  | `templateGovernance.fixtureSetHash` | Optional fixture-set identity. Defaults to `unversioned-fixtures`. |
112
140
  | `templateGovernance.governancePolicyVersion` | Optional governance policy id. Defaults to `embedded-registry`. |
113
141
  | `templateGovernance.providerActivationState` | Optional activation state. Defaults to `experimental`; production policy should require governed active templates. |
@@ -116,6 +144,51 @@ Unknown top-level keys are cloned through the JavaScript loader, but native repl
116
144
  backend verification only rely on documented policy fields. Do not place
117
145
  security-critical behavior in an unknown key.
118
146
 
147
+ ### Provider-level injection (`provider.injection`)
148
+
149
+ Top-level `injection` is trusted provider JavaScript. It runs in the managed WebView
150
+ alongside the SDK's request/response interceptor on the main page and managed popup
151
+ pages. Use it when the provider's normal UI needs help reaching the proof request:
152
+
153
+ - navigate after login to a stable account/proof page,
154
+ - click or submit provider UI that reveals the proof endpoint,
155
+ - bridge popup login flows that need provider-specific handling,
156
+ - poll the page or API for authenticated content and then post `__satyaReady`.
157
+
158
+ Supported shapes:
159
+
160
+ ```jsonc
161
+ // one script
162
+ "injection": "/* provider JS */"
163
+
164
+ // multiple scripts, executed as provider-owned WebView injection
165
+ "injection": ["/* script 1 */", "/* script 2 */"]
166
+
167
+ // explicit no-op
168
+ "injection": null
169
+ ```
170
+
171
+ Validation rules:
172
+
173
+ - a script must be a non-empty string after trimming,
174
+ - an array must not be empty,
175
+ - each script is capped at 64 KiB,
176
+ - total provider injection is capped at 128 KiB,
177
+ - `login.injection` is invalid; provider injection always belongs at the provider top
178
+ level.
179
+
180
+ `__satyaReady` is a message contract from provider-level injection to the SDK:
181
+
182
+ ```js
183
+ window.ReactNativeWebView.postMessage(JSON.stringify({ type: '__satyaReady' }));
184
+ ```
185
+
186
+ When the SDK receives that message it marks the provider session as login-ready and
187
+ releases any matching request that was being held. Endpoint `capture.requireLoginSignal`
188
+ opts an endpoint into this extra gate. Use it only when response status is not enough,
189
+ for example when a provider can return a 2xx placeholder before authenticated content is
190
+ actually available.
191
+
119
192
  ## Endpoints
120
193
 
121
194
  Each provider can define multiple endpoints for the same site:
@@ -136,13 +209,21 @@ Required endpoint fields:
136
209
 
137
210
  | Field | Description |
138
211
  |---|---|
139
- | `id` | Endpoint id. It must start with a letter and contain only letters, numbers, `_`, or `-`. |
140
- | `url` | HTTPS replay URL. The host must match `tlsIdentityPolicy.expectedSni`. |
141
- | `method` | HTTP method. Supported values are `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, and `OPTIONS`. |
142
- | `headers` | Non-empty request-header allowlist used by native replay. This is the collapsed replacement for `privacyPolicy.allowedRequestHeaders`. |
143
- | `responseType` | Response parser type. One of `json`, `html`, or `text`. `html`/`text` endpoints disclose values via `regex` reveals (see below). |
144
- | `requestMatchRules` | Non-empty array of rules used to detect the WebView request before native replay. |
145
- | `revealRules` | Non-empty array of disclosure rules. It must include at least one `RECV BODY` reveal (`json`, `regex`, or `jsonRegex`). |
212
+ | `id` | Endpoint id. It must start with a letter, contain only letters, numbers, `_`, or `-`, and be unique within the provider. Use stable ids like `primary`, `profile`, or `orders` because the id participates in `parserHash`. |
213
+ | `url` | HTTPS replay URL. The host must match `tlsIdentityPolicy.expectedSni`. For fixed API endpoints this is the exact URL native replay uses. For `replayCapturedUrl` endpoints it is a stable template/prefix that still pins the expected host. |
214
+ | `method` | HTTP method. Supported values are `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, and `OPTIONS`. It must agree with the required `methodEquals` request match rule. |
215
+ | `headers` | Non-empty request-header allowlist used by native replay. Only these captured/requested headers may be forwarded to the native replay. Include `cookie` for cookie-authenticated endpoints and `user-agent` when provider behavior depends on it. Endpoint `capture.headers` are automatically added to this allowlist. |
216
+ | `responseType` | Response parser type. One of `json`, `html`, or `text`. `json` endpoints can use `json`, `jsonRegex`, or `regex` reveals. `html`/`text` endpoints disclose values via `regex` reveals only. |
217
+ | `requestMatchRules` | Non-empty array of rules used to detect the WebView request before native replay. The current validator requires a method rule and a URL rule. Keep these narrow enough that the SDK captures the intended proof request only. |
218
+ | `revealRules` | Non-empty array of disclosure rules. It must include at least one `RECV BODY` reveal (`json`, `regex`, or `jsonRegex`). These rules define the actual claims emitted in the artifact and are part of `parserHash`. |
219
+
220
+ Optional endpoint fields:
221
+
222
+ | Field | Description |
223
+ |---|---|
224
+ | `capture` | Endpoint-scoped capture/active-fetch/readiness object. Use this when the SDK must actively fire an API request from inside the WebView or hold a matched request until `__satyaReady`. This object is not provider JavaScript; provider JavaScript belongs at top-level `provider.injection`. |
225
+ | `replayCapturedUrl` | Boolean. When `true`, native replay uses the exact URL captured from the WebView instead of the endpoint template `url`. Use for provider URLs with dynamic path/query values such as per-account user ids. The captured URL is still constrained by host/SNI and match rules. |
226
+ | `htmlCaptureBodyPattern` | Regex string for `html`/`text` endpoints loaded by top-level navigation. The SDK waits until the current document text matches this pattern before it re-issues the page as a credentialed fetch for capture. Use it for redirect chains or pages whose proof data appears only after the settled HTML loads. |
146
227
 
147
228
  The raw endpoint schema intentionally does not include `allowedResponseBodyJsonPaths`.
148
229
  The loader derives the response reveal allowlist from `revealRules` and emits a
@@ -163,17 +244,25 @@ managed WebView lands on a URL that matches an `html`/`text` provider's
163
244
  the normal capture → native-replay path runs. A provider `injection` can drive the WebView
164
245
  to the proof page after login (the bundled HTML providers do this).
165
246
 
247
+ For redirect chains where the final page URL is not known ahead of time, set
248
+ `replayCapturedUrl: true` and `htmlCaptureBodyPattern` on the endpoint. The SDK waits
249
+ until the loaded document text matches that trusted regex, then captures the current
250
+ settled URL instead of the fixed template URL. If the endpoint must use a broad URL regex,
251
+ add a `headerEquals` request rule for `x-satya-html-capture: 1`; the SDK adds that marker
252
+ only to its gated HTML-capture fetch and native replay does not forward it unless the
253
+ header is explicitly allowlisted.
254
+
166
255
  When `requireProviderTemplate(providerId, registry, endpointId)` is called with an
167
256
  endpoint id, that endpoint is normalized into the compatibility `proofTarget` used by
168
257
  the native modules. If no endpoint id is supplied, the first endpoint is selected.
169
258
 
170
- ### Active-fetch trigger (`triggerFromInjection`)
259
+ ### Endpoint capture (`capture`)
171
260
 
172
261
  Some endpoints are cookie-authenticated APIs that **no page ever calls on its own** (e.g.
173
262
  `reddit.com/api/me.json`, `spotify.com/api/account-settings/v1/profile`,
174
263
  `users.roblox.com/v1/users/authenticated`). There is nothing for the interceptor to
175
- capture. Set `triggerFromInjection: true` and the SDK actively fires the request itself
176
- from inside the WebView (with cookies) once the user is logged in:
264
+ capture. Set `capture.trigger: true` and the SDK actively fires the request itself from
265
+ inside the WebView (with cookies) once the user is logged in:
177
266
 
178
267
  ```json
179
268
  {
@@ -182,7 +271,9 @@ from inside the WebView (with cookies) once the user is logged in:
182
271
  "method": "GET",
183
272
  "headers": ["accept", "user-agent", "cookie"],
184
273
  "responseType": "json",
185
- "triggerFromInjection": true,
274
+ "capture": {
275
+ "trigger": true
276
+ },
186
277
  "requestMatchRules": [
187
278
  { "type": "methodEquals", "pattern": "GET" },
188
279
  { "type": "urlContains", "pattern": "/api/me.json" }
@@ -199,35 +290,40 @@ How it works:
199
290
  the injected request comes back **2xx**. Pre-login `401`s / redirects are ignored, so it
200
291
  never captures before sign-in. (Regular, page-triggered endpoints are unaffected — they
201
292
  still capture on the request.)
202
- - Self-terminating: stops on the first 2xx, after `injectionMaxAttempts` real fetches, or a
293
+ - Self-terminating: stops on the first 2xx, after `capture.maxAttempts` real fetches, or a
203
294
  hard poll cap.
204
295
 
205
296
  Optional fields that pair with it:
206
297
 
207
298
  | Field | Description |
208
299
  |---|---|
209
- | `triggerFromInjection` | `true` to enable the active fetch for this endpoint. |
210
- | `injectionHeaders` | `{ name: value }` extra headers for the fetch. Values may be literals or `{{cookie:NAME}}` templates resolved from `document.cookie` at fire time (for non-httpOnly CSRF / app-id headers). Their names are auto-added to the request-header allowlist for native replay. |
211
- | `requestBody` | Request body for POST/PUT/PATCH (e.g. a GraphQL query). |
212
- | `injectionLandingUrl` | HTTPS page to navigate to if the fetch is stuck on a **sibling subdomain** of the proof host (so it becomes same-origin). Defaults to the proof origin root; set a stable signed-in page when the root redirects elsewhere. E.g. after login Spotify lands on `open.spotify.com`, so its endpoint sets `"https://www.spotify.com/account/"`. The poller tries the fetch from wherever it is first (so credentialed cross-origin CORS APIs like Roblox's still need no landing), and only hops after a couple of failures on a same-registrable-domain host — never across registrable domains (won't break a third-party SSO). |
213
- | `injectionPollMs` | Poll interval in ms (default `2000`, range `500`–`15000`). |
214
- | `injectionMaxAttempts` | Max real fetch attempts (default `60`, range `1`–`300`). |
300
+ | `capture.trigger` | `true` to enable the active fetch for this endpoint. |
301
+ | `capture.headers` | `{ name: value }` extra headers for the fetch. Values may be literals or `{{cookie:NAME}}` templates resolved from `document.cookie` at fire time (for non-httpOnly CSRF / app-id headers). Their names are auto-added to the request-header allowlist for native replay. |
302
+ | `capture.requestBody` | Request body for POST/PUT/PATCH (e.g. a GraphQL query). |
303
+ | `capture.landingUrl` | HTTPS page to navigate to if the fetch is stuck on a **sibling subdomain** of the proof host (so it becomes same-origin). Defaults to the proof origin root; set a stable signed-in page when the root redirects elsewhere. E.g. after login Spotify lands on `open.spotify.com`, so its endpoint sets `"https://www.spotify.com/account/"`. The poller tries the fetch from wherever it is first (so credentialed cross-origin CORS APIs like Roblox's still need no landing), and only hops after a couple of failures on a same-registrable-domain host — never across registrable domains (won't break a third-party SSO). |
304
+ | `capture.pollMs` | Poll interval in ms (default `2000`, range `500`–`15000`). |
305
+ | `capture.maxAttempts` | Max real fetch attempts (default `60`, range `1`–`300`). |
306
+ | `capture.requireLoginSignal` | Hold a matched request until provider-level `injection` posts `__satyaReady`. Use only when a provider can return a misleading 2xx before authenticated content is available. |
215
307
 
216
308
  Examples needing headers / a body:
217
309
 
218
310
  ```jsonc
219
311
  // Instagram — constant app-id + a CSRF token read from a cookie:
220
- "triggerFromInjection": true,
221
- "injectionHeaders": {
222
- "x-ig-app-id": "936619743392459",
223
- "x-csrftoken": "{{cookie:csrftoken}}",
224
- "x-requested-with": "XMLHttpRequest"
312
+ "capture": {
313
+ "trigger": true,
314
+ "headers": {
315
+ "x-ig-app-id": "936619743392459",
316
+ "x-csrftoken": "{{cookie:csrftoken}}",
317
+ "x-requested-with": "XMLHttpRequest"
318
+ }
225
319
  }
226
320
 
227
321
  // DoorDash — POST GraphQL with a body:
228
- "triggerFromInjection": true,
229
- "injectionHeaders": { "content-type": "application/json" },
230
- "requestBody": "{\"operationName\":\"consumer\",\"variables\":{},\"query\":\"query consumer { consumer { id isGuest } }\"}"
322
+ "capture": {
323
+ "trigger": true,
324
+ "headers": { "content-type": "application/json" },
325
+ "requestBody": "{\"operationName\":\"consumer\",\"variables\":{},\"query\":\"query consumer { consumer { id isGuest } }\"}"
326
+ }
231
327
  ```
232
328
 
233
329
  Notes:
@@ -239,8 +335,27 @@ Notes:
239
335
  the same call). Same-origin APIs always work.
240
336
  - `httpOnly` cookies can't be read by `{{cookie:NAME}}` (they're sent automatically by
241
337
  `credentials:'include'` anyway; only header tokens like CSRF need templating).
242
- - `triggerFromInjection`, `injectionHeaders`, `requestBody`, and the poll tuning are **not**
243
- part of the parser hash.
338
+ - `capture.trigger` is for active fetches. `capture.requireLoginSignal` can also be used
339
+ without `capture.trigger` when the provider page naturally fires the request but the
340
+ SDK should hold it until provider-level injection posts `__satyaReady`.
341
+ - `capture` active-fetch/readiness fields are **not** part of the parser hash.
342
+ - Endpoint `injection` is invalid. Provider JavaScript still uses top-level
343
+ `provider.injection`.
344
+
345
+ Validation rules for `capture`:
346
+
347
+ - `capture` must be a non-empty object when present.
348
+ - Supported keys are exactly `trigger`, `headers`, `requestBody`, `landingUrl`, `pollMs`,
349
+ `maxAttempts`, and `requireLoginSignal`.
350
+ - `trigger` and `requireLoginSignal` must be booleans.
351
+ - `headers` must be a non-empty object of valid HTTP header names to string values, at
352
+ most 20 headers. Header values must not contain newlines and are capped at 2048 chars.
353
+ - Header names are normalized to lowercase and added to endpoint `headers` so native
354
+ replay is allowed to forward them.
355
+ - `requestBody` must be a string and is capped at 32 KiB.
356
+ - `landingUrl` must be HTTPS.
357
+ - `pollMs` must be an integer in `[500, 15000]`.
358
+ - `maxAttempts` must be an integer in `[1, 300]`.
244
359
 
245
360
  ### Dynamic URLs (`replayCapturedUrl`)
246
361
 
@@ -500,6 +615,8 @@ The SDK and provider test script enforce the important invariants:
500
615
  - top-level `injection` must be a non-empty string or non-empty string array when
501
616
  present,
502
617
  - `login.injection` is rejected because injection is top-level provider policy,
618
+ - endpoint active-fetch/readiness settings must live under endpoint `capture`; endpoint
619
+ `injection` and flat endpoint keys are rejected,
503
620
  - SPKI pins must be SHA-256 base64 values,
504
621
  - parser hashes must match the canonical parser policy.
505
622
 
@@ -515,6 +632,6 @@ The SDK and provider test script enforce the important invariants:
515
632
  - Keep reveal rules narrow; every `RECV BODY` reveal becomes a disclosed claim. Prefer
516
633
  `json` for JSON APIs; use `regex` for HTML/text pages or to pull a substring; anchor
517
634
  regex patterns tightly (`"field":"([^"]+)"`) so they match exactly one value.
518
- - Treat `injection` as trusted code. Do not load registry files from untrusted hosts.
635
+ - Treat provider `injection` as trusted code. Do not load registry files from untrusted hosts.
519
636
  - Keep backend verifier policy in sync with registry changes before making
520
637
  `providerPolicyRefresh="verifier-required"` the default for a provider.
package/README.md CHANGED
@@ -94,11 +94,25 @@ Vimeo, Roblox, Skillshare, DoorDash) plus HTML/text providers that disclose valu
94
94
  regex (GitHub, Amazon, Facebook, Netflix, WordPress, Notion, DeviantArt, Zoom).
95
95
 
96
96
  The raw provider schema is documented in [`PROVIDER_CONFIG.md`](./PROVIDER_CONFIG.md).
97
- It uses the current hybrid shape: top-level provider metadata, top-level optional
98
- `injection`, a non-empty `endpoints` array, endpoint-level `headers`, request match
99
- rules, reveal rules, TLS identity policy, and template governance. The SDK normalizes
100
- the selected endpoint into the compatibility `proofTarget`/`privacyPolicy` fields used
101
- internally by native replay. If no endpoint id is requested, the first endpoint is used.
97
+ The current `providers.json` shape is intentionally small and explicit:
98
+
99
+ | Scope | Fields |
100
+ |---|---|
101
+ | Registry | `schemaVersion`, `providers` |
102
+ | Provider | `schemaVersion`, `providerId`, `name`, `login`, `endpoints`, `tlsIdentityPolicy`, `templateGovernance`, optional `iconUrl`, `description`, `userAgent`, top-level `injection` |
103
+ | Endpoint | `id`, `url`, `method`, `headers`, `responseType`, `requestMatchRules`, `revealRules`, optional endpoint `capture`, `replayCapturedUrl`, `htmlCaptureBodyPattern` |
104
+ | TLS policy | `expectedSni`, `spkiSha256B64Pins` |
105
+ | Governance | `templateHash`, `parserHash`, optional activation/governance metadata |
106
+
107
+ Top-level provider `injection` is provider-owned JavaScript that runs in the managed
108
+ WebView. Endpoint `capture` is a separate object for active-fetch/readiness settings,
109
+ for example `{ "trigger": true, "headers": { ... } }`. Endpoint `injection` and old flat
110
+ endpoint fields such as `triggerFromInjection` and `injectionHeaders` are no longer
111
+ supported.
112
+
113
+ The SDK normalizes the selected endpoint into the compatibility
114
+ `proofTarget`/`privacyPolicy` fields used internally by native replay. If no endpoint id
115
+ is requested, the first endpoint is used.
102
116
 
103
117
  ### Response types and reveal rules
104
118
 
@@ -123,15 +137,19 @@ capture → native-replay path runs; a provider `injection` can navigate to the
123
137
  after login.
124
138
 
125
139
  For cookie-authenticated APIs that **no page ever calls** (e.g. Reddit/Spotify/Roblox
126
- profile APIs), set `"triggerFromInjection": true` on the endpoint: the SDK actively fires
127
- the request from inside the WebView once you're signed in, gated on a 2xx response so it
128
- never captures before login. Pair it with `injectionHeaders` (literals or `{{cookie:NAME}}`
129
- templates, for CSRF/app-id headers) and `requestBody` (for POST). See
130
- [`PROVIDER_CONFIG.md`](./PROVIDER_CONFIG.md) for full details and examples.
140
+ profile APIs), set endpoint `"capture": { "trigger": true }`: the SDK actively fires the
141
+ request from inside the WebView once you're signed in, gated on a 2xx response so it
142
+ never captures before login. Pair it with `capture.headers` (literals or
143
+ `{{cookie:NAME}}` templates, for CSRF/app-id headers), `capture.requestBody` (for POST),
144
+ `capture.landingUrl` (when the proof API lives on a sibling subdomain), and
145
+ `capture.requireLoginSignal` (only when a provider script must post `__satyaReady`
146
+ before replay). See [`PROVIDER_CONFIG.md`](./PROVIDER_CONFIG.md) for full details and
147
+ examples.
131
148
 
132
149
  Provider templates may include top-level `injection` JavaScript, as a string or string
133
150
  array, when a provider needs page automation during login/request discovery. The managed
134
151
  WebView runs those scripts with the SDK network interceptor on every main and popup page.
152
+ Endpoint-level `capture` is a separate object for active-fetch/readiness settings.
135
153
 
136
154
  Useful exports:
137
155
 
@@ -162,10 +180,10 @@ endpoint response types, and reveal rules. Run `npm run test:providers` after ed
162
180
 
163
181
  ## Installation Options
164
182
 
165
- Every install path also needs the WebView peer dependency:
183
+ Every install path also needs the WebView and safe-area peer dependencies:
166
184
 
167
185
  ```bash
168
- npx expo install react-native-webview
186
+ npx expo install react-native-webview react-native-safe-area-context
169
187
  ```
170
188
 
171
189
  Use npm for released apps:
@@ -184,7 +202,7 @@ npm run check:native-artifacts
184
202
 
185
203
  cd /path/to/your-expo-app
186
204
  npm install /path/to/tls-app-attest/platform_sdks/expo-satya-attest
187
- npx expo install react-native-webview
205
+ npx expo install react-native-webview react-native-safe-area-context
188
206
  ```
189
207
 
190
208
  Re-run `npm run build` in the SDK directory after TypeScript edits. Re-run the native
@@ -197,7 +215,7 @@ would publish:
197
215
 
198
216
  ```bash
199
217
  npm install https://github.com/<owner>/<repo>/releases/download/expo-satya-attest-v0.2.2/burnt-labs-expo-satya-attest-0.2.2.tgz
200
- npx expo install react-native-webview
218
+ npx expo install react-native-webview react-native-safe-area-context
201
219
  ```
202
220
 
203
221
  Installing from a Git ref also works when that ref has the SDK package at the repository
@@ -206,7 +224,7 @@ root, such as a dedicated SDK repo or a subtree/split branch:
206
224
  ```bash
207
225
  npm install github:<owner>/<sdk-repo>#v0.2.2
208
226
  npm install git+https://github.com/<owner>/<sdk-repo>.git#v0.2.2
209
- npx expo install react-native-webview
227
+ npx expo install react-native-webview react-native-safe-area-context
210
228
  ```
211
229
 
212
230
  Do not point npm at the monorepo root unless that Git ref is prepared so
@@ -4,13 +4,13 @@ plugins {
4
4
  }
5
5
 
6
6
  group = 'expo.modules.satyaattest'
7
- version = '0.2.4'
7
+ version = '0.3.0'
8
8
 
9
9
  android {
10
10
  namespace "expo.modules.satyaattest"
11
11
  defaultConfig {
12
12
  versionCode 1
13
- versionName "0.2.4"
13
+ versionName "0.3.0"
14
14
  // StrongBox key attestation needs API 28+; basic Keystore attestation API 24+.
15
15
  minSdkVersion 24
16
16
  }
@@ -77,6 +77,8 @@ private const val MAX_RESPONSE_BODY_BYTES = 8L * 1024 * 1024
77
77
  private const val PLAY_INTEGRITY_BIND_DOMAIN = "satya-w-playintegrity-bind-v1"
78
78
 
79
79
  class SatyaAttestModule : Module() {
80
+ private data class BoundedResponseBody(val bytes: ByteArray, val text: String)
81
+
80
82
  @Volatile private var transportConfigJson: String = "{}"
81
83
  private val documentStartScriptHandlers = mutableMapOf<Int, ScriptHandler>()
82
84
 
@@ -541,11 +543,11 @@ class SatyaAttestModule : Module() {
541
543
  // legacy json-path-only policy for older normalized templates.
542
544
  val reveals = privacyPolicy.optJSONArray("allowedResponseReveals")
543
545
  val claims = if (reveals != null && reveals.length() > 0) {
544
- extractRevealClaims(responseBody, reveals)
546
+ extractRevealClaims(responseBody.text, reveals)
545
547
  } else {
546
548
  val jsonPaths = privacyPolicy.getJSONArray("allowedResponseBodyJsonPaths")
547
549
  val claimAliases = responseClaimAliases(template, jsonPaths)
548
- extractClaims(responseBody, jsonPaths, claimAliases)
550
+ extractClaims(responseBody.text, jsonPaths, claimAliases)
549
551
  }
550
552
  require(claims.length() > 0) { "native replay response did not contain any allowed claim value" }
551
553
 
@@ -562,7 +564,7 @@ class SatyaAttestModule : Module() {
562
564
  put("finalUrl", response.request.url.toString())
563
565
  put("contentType", response.header("content-type"))
564
566
  put("contentEncoding", response.header("content-encoding"))
565
- put("responseSha256Hex", hex(sha256(responseBody.toByteArray())))
567
+ put("responseSha256Hex", hex(sha256(responseBody.bytes)))
566
568
  put("claims", claims)
567
569
  put(
568
570
  "tlsEvidence",
@@ -602,6 +604,18 @@ class SatyaAttestModule : Module() {
602
604
  private fun capturedRequestMatchesRule(rule: JSONObject, captured: JSONObject): Boolean {
603
605
  return when (rule.optString("type")) {
604
606
  "urlContains" -> captured.optString("url").contains(rule.optString("pattern"))
607
+ "urlRegex" -> {
608
+ val pattern = rule.optString("pattern")
609
+ pattern.isNotBlank() && runCatching {
610
+ val regex = Regex(pattern)
611
+ val url = captured.optString("url")
612
+ val pathAndQuery = runCatching {
613
+ val parsed = URL(url)
614
+ parsed.path + (parsed.query?.let { "?$it" } ?: "")
615
+ }.getOrDefault("")
616
+ regex.containsMatchIn(url) || (pathAndQuery.isNotEmpty() && regex.containsMatchIn(pathAndQuery))
617
+ }.getOrDefault(false)
618
+ }
605
619
  "methodEquals" -> captured.optString("method").uppercase() == rule.optString("pattern").uppercase()
606
620
  "headerEquals" -> {
607
621
  val key = rule.optString("key").lowercase()
@@ -795,9 +809,13 @@ class SatyaAttestModule : Module() {
795
809
  else -> null
796
810
  }
797
811
  if (value == null || value == JSONObject.NULL) continue
812
+ // For json/jsonRegex the disclosure is keyed by the JSON path it was read from. For a
813
+ // pure regex reveal there is no JSON path, so key the disclosure by the (validated,
814
+ // unique) alias — a single-segment JSON path the core can insert + read back, instead
815
+ // of the synthetic "regex(...)" string the core would wrongly parse as a JSON path.
798
816
  val sourcePath = when (type) {
799
817
  "json", "jsonRegex" -> path
800
- else -> "regex(${reveal.optString("pattern")})"
818
+ else -> alias
801
819
  }
802
820
  claims.put(
803
821
  JSONObject().apply {
@@ -832,14 +850,15 @@ class SatyaAttestModule : Module() {
832
850
 
833
851
  // Read the response body with an upper size bound (regex/JSON extraction runs on the
834
852
  // full string). Buffers one byte past the cap to detect oversize bodies, then rejects.
835
- private fun readBoundedResponseBody(response: okhttp3.Response): String {
836
- val responseBody = response.body ?: return ""
853
+ private fun readBoundedResponseBody(response: okhttp3.Response): BoundedResponseBody {
854
+ val responseBody = response.body ?: return BoundedResponseBody(ByteArray(0), "")
837
855
  val source = responseBody.source()
838
856
  source.request(MAX_RESPONSE_BODY_BYTES + 1)
839
857
  require(source.buffer.size <= MAX_RESPONSE_BODY_BYTES) {
840
858
  "native replay response exceeds $MAX_RESPONSE_BODY_BYTES bytes"
841
859
  }
842
- return responseBody.string()
860
+ val bytes = responseBody.bytes()
861
+ return BoundedResponseBody(bytes, bytes.toString(Charsets.UTF_8))
843
862
  }
844
863
 
845
864
  private fun jsonPathGet(root: Any, path: String): Any? {
@@ -92,14 +92,7 @@ export interface SatyaProviderLogin {
92
92
  url: string;
93
93
  [key: string]: unknown;
94
94
  }
95
- export interface SatyaProviderEndpoint {
96
- id: string;
97
- url: string;
98
- method: string;
99
- headers: string[];
100
- responseType: string;
101
- requestMatchRules: Record<string, unknown>[];
102
- revealRules: Record<string, unknown>[];
95
+ export interface SatyaProviderEndpointCapture {
103
96
  /**
104
97
  * When true, the SDK actively fires this endpoint's request from inside the managed
105
98
  * WebView (via an injected `fetch`) once the user is logged in, instead of waiting for
@@ -107,14 +100,14 @@ export interface SatyaProviderEndpoint {
107
100
  * the native replay before login. Use for cookie-authenticated APIs that no page calls
108
101
  * on its own (e.g. Reddit/Spotify/Roblox profile APIs).
109
102
  */
110
- triggerFromInjection?: boolean;
103
+ trigger?: boolean;
111
104
  /**
112
- * Extra request headers for the injected active fetch (only used with
113
- * `triggerFromInjection`). Values may be literals or `{{cookie:NAME}}` templates resolved
114
- * from `document.cookie` at fire time (for non-httpOnly CSRF/app-id headers). Header
115
- * names are automatically added to the request-header allowlist for native replay.
105
+ * Extra request headers for the injected active fetch. Values may be literals or
106
+ * `{{cookie:NAME}}` templates resolved from `document.cookie` at fire time (for
107
+ * non-httpOnly CSRF/app-id headers). Header names are automatically added to the
108
+ * request-header allowlist for native replay.
116
109
  */
117
- injectionHeaders?: Record<string, string>;
110
+ headers?: Record<string, string>;
118
111
  /** Request body for the injected active fetch (POST/PUT/PATCH endpoints). */
119
112
  requestBody?: string;
120
113
  /**
@@ -123,11 +116,29 @@ export interface SatyaProviderEndpoint {
123
116
  * on `www.spotify.com`). Prefer a stable signed-in page that itself loads the proof API.
124
117
  * Defaults to the proof origin root (`https://<host>/`) when omitted.
125
118
  */
126
- injectionLandingUrl?: string;
119
+ landingUrl?: string;
127
120
  /** Poll interval in ms for the active fetch (default 2000, bounded 500..15000). */
128
- injectionPollMs?: number;
121
+ pollMs?: number;
129
122
  /** Max active-fetch attempts before giving up (default 60, bounded 1..300). */
130
- injectionMaxAttempts?: number;
123
+ maxAttempts?: number;
124
+ /**
125
+ * Holds a matched request until provider-owned top-level `injection` posts
126
+ * `__satyaReady`. Use only for providers where a status-only 2xx login gate is not
127
+ * enough to prove authenticated content is available.
128
+ */
129
+ requireLoginSignal?: boolean;
130
+ [key: string]: unknown;
131
+ }
132
+ export interface SatyaProviderEndpoint {
133
+ id: string;
134
+ url: string;
135
+ method: string;
136
+ headers: string[];
137
+ responseType: string;
138
+ requestMatchRules: Record<string, unknown>[];
139
+ revealRules: Record<string, unknown>[];
140
+ /** Endpoint-scoped capture/active-fetch/readiness config. */
141
+ capture?: SatyaProviderEndpointCapture;
131
142
  /**
132
143
  * Replay the URL the WebView actually fetched, instead of the fixed template `url`. Use for
133
144
  * endpoints whose path has a dynamic segment (e.g. a user id, like Garmin's
@@ -135,6 +146,12 @@ export interface SatyaProviderEndpoint {
135
146
  * The captured URL is still constrained to the pinned host and the endpoint's match rules.
136
147
  */
137
148
  replayCapturedUrl?: boolean;
149
+ /**
150
+ * For `html`/`text` proof pages loaded by top-level navigation, only re-issue the
151
+ * current document URL for capture once the loaded document text matches this trusted
152
+ * regex. Useful for redirect chains where the proof data appears only on the settled page.
153
+ */
154
+ htmlCaptureBodyPattern?: string;
138
155
  [key: string]: unknown;
139
156
  }
140
157
  export interface SatyaProviderTemplate {
@@ -1 +1 @@
1
- {"version":3,"file":"SatyaAttest.types.d.ts","sourceRoot":"","sources":["../src/SatyaAttest.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SatyaAttest.types.d.ts","sourceRoot":"","sources":["../src/SatyaAttest.types.ts"],"names":[],"mappings":"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"}