@goliapkg/sentori-react-native 7.0.0 → 7.0.1
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/README.md +25 -1
- package/android/src/main/java-core/com/sentori/SentoriConfig.kt +1 -1
- package/android/src/main/java-core/com/sentori/SentoriNativeSignals.kt +1 -2
- package/android/src/main/java-core/com/sentori/SentoriPush.kt +36 -3
- package/android/src/main/java-core/com/sentori/SentoriScope.kt +17 -1
- package/android/src/main/java-core/com/sentori/SentoriTransport.kt +30 -4
- package/android/src/test/java-core/com/sentori/SentoriTransportTest.kt +82 -0
- package/ios/core/SentoriHangWatchdog.swift +3 -3
- package/ios/core/SentoriThreadSampler.swift +3 -3
- package/lib/handlers/network.js +2 -2
- package/lib/handlers/network.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/init.js +2 -2
- package/lib/init.js.map +1 -1
- package/lib/long-task-monitor.js +1 -1
- package/lib/long-task-monitor.js.map +1 -1
- package/lib/mobile-vitals.js +2 -2
- package/lib/mobile-vitals.js.map +1 -1
- package/lib/push.d.ts.map +1 -1
- package/lib/push.js +39 -7
- package/lib/push.js.map +1 -1
- package/lib/rage-tap.js +2 -2
- package/lib/rage-tap.js.map +1 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +18 -1
- package/lib/scope.js.map +1 -1
- package/lib/transport.js +2 -2
- package/lib/transport.js.map +1 -1
- package/lib/verbs.js +3 -3
- package/lib/verbs.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/iron-rule.test.ts +79 -1
- package/src/__tests__/push.test.ts +38 -0
- package/src/handlers/network.ts +2 -2
- package/src/index.ts +1 -1
- package/src/init.ts +2 -2
- package/src/long-task-monitor.ts +1 -1
- package/src/mobile-vitals.ts +2 -2
- package/src/push.ts +42 -6
- package/src/rage-tap.tsx +2 -2
- package/src/scope.ts +19 -1
- package/src/transport.ts +2 -2
- package/src/verbs.ts +3 -3
- package/ios/PRIVACY_AND_REVIEW.md +0 -122
package/src/transport.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Event transport — the only place the SDK talks to the network.
|
|
2
2
|
//
|
|
3
|
-
// Quiet by default, complete when it matters
|
|
3
|
+
// Quiet by default, complete when it matters: events
|
|
4
4
|
// batch on a 5 s timer or a 10-deep queue, whichever first; assert
|
|
5
5
|
// pass-counts piggyback on whatever batch goes out next (never their
|
|
6
6
|
// own request); failures back off and finally persist to an offline
|
|
@@ -20,7 +20,7 @@ const STORAGE_KEY = '@sentori/pending';
|
|
|
20
20
|
const MAX_PERSISTED = 1000;
|
|
21
21
|
|
|
22
22
|
// Pinned to package.json by a test — bump both together.
|
|
23
|
-
const SDK_VERSION = '7.0.
|
|
23
|
+
const SDK_VERSION = '7.0.1';
|
|
24
24
|
|
|
25
25
|
let _queue: WireEvent[] = [];
|
|
26
26
|
let _assertStats = new Map<string, AssertStat>();
|
package/src/verbs.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// The five event verbs
|
|
1
|
+
// The five event verbs. Everything here is
|
|
2
2
|
// synchronous, never throws, and returns the client-minted event id
|
|
3
3
|
// — the zero-cost iron rule made code.
|
|
4
4
|
//
|
|
@@ -36,7 +36,7 @@ import { countAssert, enqueue } from './transport';
|
|
|
36
36
|
declare const __DEV__: boolean | undefined;
|
|
37
37
|
|
|
38
38
|
/** Serialize any Error instances found in the data argument — the
|
|
39
|
-
* error-in-data convention
|
|
39
|
+
* error-in-data convention: a caught-but-noteworthy
|
|
40
40
|
* exception needs no special API. One level deep is enough; nested
|
|
41
41
|
* containers of errors are an anti-pattern we don't reward. */
|
|
42
42
|
const serializeData = (data?: EventData): Record<string, unknown> | undefined => {
|
|
@@ -220,7 +220,7 @@ export const assert = safeFn(
|
|
|
220
220
|
|
|
221
221
|
export const probe = safeFn('probe', (ref: string, data?: EventData): string => {
|
|
222
222
|
// A tripwire: reaching this call IS the signal. Never throws,
|
|
223
|
-
// never changes control flow
|
|
223
|
+
// never changes control flow.
|
|
224
224
|
return emit('probe', { name: ref, data });
|
|
225
225
|
});
|
|
226
226
|
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
# iOS Main Thread Sampler — Privacy & App Store Review Notes
|
|
2
|
-
|
|
3
|
-
> **Status:** Phase 29 sub-A step 1. Documents the Mach + pthread + dyld
|
|
4
|
-
> APIs the upcoming `SentoriThreadSampler.swift` will call, the App
|
|
5
|
-
> Store review risk for each, and the privacy boundary. Written before
|
|
6
|
-
> the Swift implementation lands so we can rule API choices in or out
|
|
7
|
-
> before writing code we'd later need to rip out.
|
|
8
|
-
|
|
9
|
-
## Why we need this
|
|
10
|
-
|
|
11
|
-
`SentoriHangWatchdog.swift` currently captures
|
|
12
|
-
`Thread.callStackSymbols` from the watchdog thread itself, not from
|
|
13
|
-
main, because main is wedged when we want to sample it. The captured
|
|
14
|
-
stack therefore points into our own timer machinery, which is useless
|
|
15
|
-
for diagnosing the user's hang. (The file's own comment at line 100
|
|
16
|
-
flags this as a stop-gap.)
|
|
17
|
-
|
|
18
|
-
To get the actual wedged main-thread frames we have to walk a remote
|
|
19
|
-
thread's frame pointer chain — main is alive but not running our
|
|
20
|
-
code, so we resolve it via Mach + pthread APIs. This document checks
|
|
21
|
-
those APIs against App Store Review Guideline 2.5.1 ("Apps must use
|
|
22
|
-
only public APIs") before we commit to them.
|
|
23
|
-
|
|
24
|
-
## API inventory
|
|
25
|
-
|
|
26
|
-
### Public, App Store-safe
|
|
27
|
-
|
|
28
|
-
| API | Header | Purpose | Risk |
|
|
29
|
-
|---|---|---|---|
|
|
30
|
-
| `pthread_main_np()` | `<pthread.h>` | bool: am I on main? Sanity-check before sampling. | none |
|
|
31
|
-
| `pthread_self()` | `<pthread.h>` | get current pthread for `pthread_mach_thread_np`. | none |
|
|
32
|
-
| `pthread_mach_thread_np(pthread_t)` | `<pthread.h>` | pthread → mach port. The `_np` suffix is Apple's mark for "non-portable extension"; it's a public API, just not POSIX-portable. | none |
|
|
33
|
-
| `mach_task_self()` | `<mach/mach.h>` | this process's task port. We pass our own task only; we never look up another. | none |
|
|
34
|
-
| `thread_get_state(thread, ARM_THREAD_STATE64, ...)` | `<mach/thread_act.h>` | read main thread's PC / FP / SP / LR. Same call sentry-cocoa, Firebase Crashlytics, and Bugsnag use. | low — public Mach API; reviewers expect to see it from crash-reporter SDKs. |
|
|
35
|
-
| `vm_read_overwrite(self_task, addr, size, dst, ...)` | `<mach/vm_map.h>` | safe (no SIGSEGV) read of own-process memory. We restrict to `mach_task_self()` and small reads (each frame is two pointers). | low — public; flagged only when used to read other processes' memory. |
|
|
36
|
-
| `_dyld_image_count()` / `_dyld_get_image_header()` / `_dyld_get_image_vmaddr_slide()` / `_dyld_get_image_uuid()` | `<mach-o/dyld.h>` | LC_UUID for dSYM matching, ASLR slide for offset calc. Public dyld API. | none |
|
|
37
|
-
|
|
38
|
-
### Explicitly NOT used (private API risk)
|
|
39
|
-
|
|
40
|
-
| API | Why we don't use it |
|
|
41
|
-
|---|---|
|
|
42
|
-
| `_pthread_main_thread_np` (underscore prefix) | private alias of `pthread_main_np()`; underscore prefix in Apple SDK = SPI, rejection-grade. |
|
|
43
|
-
| `task_threads(other_task, ...)` cross-task | requires `task-port` entitlement and is reviewer-flagged. We only ever look at our own task. |
|
|
44
|
-
| `task_for_pid` | gated by entitlement; not appropriate for our same-process use. |
|
|
45
|
-
| `__platform_call_*` / `kdebug_trace` / signal hooking | private. |
|
|
46
|
-
| `_dyld_register_func_for_*` introspection beyond UUID | not needed for stack walking. |
|
|
47
|
-
|
|
48
|
-
## Why this is App Store safe
|
|
49
|
-
|
|
50
|
-
Direct prior art shipping the same call set, no review issues:
|
|
51
|
-
|
|
52
|
-
- **sentry-cocoa** — uses `thread_get_state` + `vm_read_overwrite` for
|
|
53
|
-
slow-frame and ANR sampling, in millions of apps.
|
|
54
|
-
- **Firebase Crashlytics** — same primitives for ANR + hang capture.
|
|
55
|
-
- **Bugsnag**, **Embrace** — likewise.
|
|
56
|
-
- **Apple's MetricKit** (`MXCallStackTree`) walks call stacks via the
|
|
57
|
-
same public Darwin primitives. Apple themselves consume this
|
|
58
|
-
surface.
|
|
59
|
-
|
|
60
|
-
Apple's stance: Review Guideline 2.5.1 forbids non-public APIs, but
|
|
61
|
-
"non-public" means undocumented / underscore-prefixed / not in the
|
|
62
|
-
public SDK. All calls in the public-safe table above are documented
|
|
63
|
-
in Apple's developer reference and shipped in `<mach/...>` /
|
|
64
|
-
`<pthread.h>` / `<mach-o/dyld.h>` headers that come with Xcode by
|
|
65
|
-
default.
|
|
66
|
-
|
|
67
|
-
## Privacy considerations
|
|
68
|
-
|
|
69
|
-
What we capture per hang event:
|
|
70
|
-
|
|
71
|
-
- Up to 64 PC values (program counter addresses) from the main
|
|
72
|
-
thread's frame pointer chain.
|
|
73
|
-
- The `LC_UUID` of each loaded image and its ASLR vmaddr slide, so
|
|
74
|
-
the server can match PCs back to a dSYM (Phase 22 sub-B field).
|
|
75
|
-
- Hang duration in milliseconds (already captured today).
|
|
76
|
-
|
|
77
|
-
What we explicitly do NOT capture:
|
|
78
|
-
|
|
79
|
-
- Other processes' memory. We only pass `mach_task_self()` to
|
|
80
|
-
`vm_read_overwrite`.
|
|
81
|
-
- Function arguments, local variables, or register contents — PC
|
|
82
|
-
only, never the rest of the `arm_thread_state64_t` struct.
|
|
83
|
-
- Heap content, NSString contents, user-typed text, PII.
|
|
84
|
-
- Continuous-rate samples. Sampling fires only on a detected hang
|
|
85
|
-
(≥ 2s main-thread block) and is one-shot per hang (see watchdog
|
|
86
|
-
`reportedThisHang` flag at `SentoriHangWatchdog.swift:54`).
|
|
87
|
-
|
|
88
|
-
Symbolication happens **server-side** against the uploaded dSYM
|
|
89
|
-
(`server/src/symbolicate.rs`). On-device,
|
|
90
|
-
`frames[].instructionAddress` is an ASLR-slid pointer with no
|
|
91
|
-
semantic content until paired with the dSYM.
|
|
92
|
-
|
|
93
|
-
For the user-facing privacy doc (what data Sentori collects and why),
|
|
94
|
-
see `docs/legal/privacy.md`.
|
|
95
|
-
|
|
96
|
-
## Rejection contingency
|
|
97
|
-
|
|
98
|
-
If Apple Review ever rejects with reference to `vm_read_overwrite` or
|
|
99
|
-
`thread_get_state`:
|
|
100
|
-
|
|
101
|
-
1. Confirm sentry-cocoa / Firebase / Bugsnag are still shipping the
|
|
102
|
-
same call set. They're the canary; rejection there means a policy
|
|
103
|
-
change everyone needs to handle.
|
|
104
|
-
2. Switch to `backtrace()` from `<execinfo.h>` — pure libc, walks
|
|
105
|
-
only the *current* thread, which is the watchdog thread, not
|
|
106
|
-
main. Lower fidelity (back where we started), zero risk.
|
|
107
|
-
3. Last resort: ship without main-thread sampler; emit hang events
|
|
108
|
-
with empty `frames[]` and `tags.source = "sentori.hangWatchdog.no-sampler"`
|
|
109
|
-
so the dashboard can flag the gap. Feature degrades, doesn't
|
|
110
|
-
break.
|
|
111
|
-
|
|
112
|
-
## Implementation references
|
|
113
|
-
|
|
114
|
-
- `sdk/react-native/ios/SentoriThreadSampler.swift` — to be created in
|
|
115
|
-
Phase 29 sub-A step 2: `captureMainThreadFrames(maxFrames: Int = 64) -> [(pc: UInt64, fp: UInt64)]`
|
|
116
|
-
- `sdk/react-native/ios/SentoriHangWatchdog.swift` — current
|
|
117
|
-
`Thread.callStackSymbols` capture (line 108) replaced by sampler
|
|
118
|
-
call in step 4.
|
|
119
|
-
- `server/src/symbolicate.rs` — dSYM lookup + frame resolution
|
|
120
|
-
(existing, Phase 22 sub-B).
|
|
121
|
-
- `docs/protocol.md` — `frames[].instructionAddress` + `debugId` +
|
|
122
|
-
`arch` field definitions (existing, Phase 22 sub-B).
|