Documentation Index
Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt
Use this file to discover all available pages before exploring further.
The behavior SDK’s privacy posture is the difference between “this thing is invasive” and “this thing is acceptable to ship”. This page is the audit-grade reference: every claim mapped to source.
What is collected
| Surface | Captured | Not captured |
|---|
| Scroll | direction, velocity, acceleration, jitter | what was scrolled |
| Tap | timing, count, pressure (when available) | what was tapped (no view ids, no labels) |
| Swipe | direction, timing | content swiped |
| Typing | inter-key intervals, burst length, cadence | keystrokes, IME state, text content, language |
| App switch | timing of foreground change | app names, package ids (collected internally for session bookkeeping but not emitted in events) |
| Notification | timing, InterruptionAction (ignored / opened / answered / dismissed) | notification title, body, app source, user response content |
| Call | timing, InterruptionAction | caller id, contact name, audio |
| Clipboard | ClipboardAction (copy / paste / cut), ClipboardContext (text-field / system) | clipboard contents |
| Motion | 50 Hz triaxial accelerometer (m/s²) when emitRawMotionSamples or enableMotionLite enabled | gyro / magnetometer / GPS / barometer / camera / mic |
What is never captured
The following classes are not collected by any code path:
- Text content (typed, displayed, or in clipboard).
- Audio (mic).
- Images (camera, screenshots).
- Location (GPS, network location, geofencing).
- Contacts.
- Calendar entries.
- Browser history.
- Network requests originating from the app (the SDK does not call out to the network at all — see “Outbound traffic” below).
Outbound traffic
The SDK itself makes no outbound network calls. There is no HTTP client in the synheart-behavior source. Cloud delivery, when desired, happens through synheart-core → the Synheart runtime’s ingest connector, which:
- Gates on
Behavior and cloudUpload consent.
- Hashes
subject_id; the raw value never leaves the device.
- Signs requests with the device’s hardware key (see Synheart Auth).
The SDK alone does not transmit any data anywhere.
| Permission | Required for | Scope |
|---|
| Notification listener (Android) | notification events with InterruptionAction | The SDK uses NotificationListenerService which observes notification posts. It records timing + action only; the listener never reads notification text. |
| Phone state / call log (Android) | call events | Timing and ignored/answered enum only; no caller id stored or emitted. |
| Accelerometer (sensor) | Motion-lite + raw motion samples | Standard sensor access; no special platform prompt on iOS/Android. |
| Accessibility service (NOT used) | — | The SDK does not request Accessibility on Android. Some apps use Accessibility for keystroke logging; this SDK does not. |
| HealthKit (iOS) | (none) | Behavior SDK does not touch HealthKit; that’s synheart-wear’s domain. |
SynheartBehavior.checkNotificationPermission() / requestNotificationPermission() and the call-permission equivalents are Android-only; iOS does not have a comparable user-facing permission for these surfaces, and the SDK collects only what iOS exposes through public APIs.
Adversary model
| Adversary | Concern | Mitigation |
|---|
| Malicious app on same device | Reading SDK-collected data via shared storage | The SDK does not write events to disk. Aggregates flow only through in-memory streams to the host app. |
| Compromised host process | Host can read everything in its address space | Out of scope: the SDK runs inside the host. Trust boundary is at the OS, not within the process. |
| Network adversary | Intercept telemetry | The SDK makes no network calls. When the host forwards events through the Synheart runtime, transport is TLS + device-signed proof. |
| Server-side observer | Reconstruct user identity from behavioral patterns | subject_id is hashed; no app names or content reach the cloud. Mitigations are at the cloud-policy layer. |
| Curious developer | Use the SDK in ways the user didn’t expect | Consent gates at three layers: SDK config (consentBehavior), runtime (Behavior consent), and platform OS permission grants. |
Implementation invariants
When auditing the SDK against this threat model, the following are non-negotiable code invariants:
- No string captured from input fields.
BehaviorEventType.typing events carry only timing fields in their metrics map.
- No clipboard contents.
ClipboardAction and ClipboardContext enums encode the action/location, not the payload.
- No notification body or title.
InterruptionAction enum is the only notification-derived field on events.
- No outbound HTTP from the SDK. No HTTP clients imported in any of the four SDK packages.
- No background data persistence by the SDK. Events flow through streams; aggregates are computed in-memory and surface as
BehaviorSessionSummary. Hosts decide whether to persist.
If any of these change, this page is a release blocker until the threat model is updated.
Consent gating layers
Host config: BehaviorConfig.consentBehavior (boolean)
↓
SDK runtime: On startSession, the SDK checks consent
↓
Core SDK gate: ConsentModule.has_consent(behavior)
↓
Runtime gate: ConsentType::Behavior (Synheart runtime)
↓
Cloud gate: ConsentType::CloudUpload (separate)
All four gates must allow for behavioral data to leave the device. Any one closes the loop.
Logging policy
The SDK logs at info / warn levels in production. Logs include:
- Session lifecycle (
session_start, session_end, durations).
- Permission state changes.
- Inference latency (motion-lite).
The SDK does not log:
- Event-level payloads (no event-by-event logs).
- User identifiers (raw
userId / deviceId are never written to logs unless the host injects them).
- Motion sample bytes.
- Inference inputs.