mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 16:03:49 +00:00
* fix(mobile): restore pairing self-heal and recover a wedged handshake readPairingKeychainItem threw when an Android presence record pointed at a SecureStore entry that read back null. Android reports absent and undecryptable identically, so the keystore fault the presence record was added to survive latched every caller out of its own orphan cleanup: the pairing journal store never reached its null-secret branch, stale winner-stamped metadata survived, and every later QR scan failed with "mobile relay pairing recovery pending". Report absent instead and drop the stale presence claim, still without falling back to the superseded older generation. The handshake-timeout path closed the socket with no handleSocketClosed fallback, unlike the connect-timeout and activity-probe paths. When React Native omits onclose for a wedged transport the client stayed in 'handshaking' forever with no reconnect armed. * fix(mobile): keep the presence pin when a recorded keychain item reads null Clearing the presence record on the self-heal removed the only thing that stops readPairingKeychainItem's generation walk, so the next read fell back to the superseded value under an older generation -- exactly what #11430's presence record exists to prevent, and reachable for host device tokens and relay resume bundles after an Android encrypt rotation. Return null and leave the record in place; the null return alone unlatches every caller's orphan cleanup, and delete/re-pair already clear or re-stamp the record. Co-authored-by: Orca <help@stably.ai> * fix(mobile): date synthesized socket closes in transport diagnostics Move the log-only close clocks behind handleSocketClosed's stale guard so a synthesized close records them and a late onclose can't clobber the replacement. Co-authored-by: Orca <help@stably.ai> * fix(mobile): account for delayed synthesized closes --------- Co-authored-by: Orca <help@stably.ai>
43 lines
1.1 KiB
TypeScript
43 lines
1.1 KiB
TypeScript
// Why: RN's WebSocket close/error events are loosely typed and vary per
|
|
// platform. Serialize them defensively (circular-safe, function-safe,
|
|
// truncated) so the [net] diagnostics can never crash mid-handler.
|
|
export function describeSocketEvent(event: unknown): { keys: string[]; json: string } {
|
|
let keys: string[] = []
|
|
try {
|
|
keys = event && typeof event === 'object' ? Object.keys(event as object) : []
|
|
} catch {
|
|
keys = []
|
|
}
|
|
let json = ''
|
|
try {
|
|
const seen = new WeakSet<object>()
|
|
json = JSON.stringify(
|
|
event,
|
|
(_k, v) => {
|
|
if (typeof v === 'object' && v !== null) {
|
|
if (seen.has(v as object)) {
|
|
return '[circular]'
|
|
}
|
|
seen.add(v as object)
|
|
}
|
|
if (typeof v === 'function') {
|
|
return '[fn]'
|
|
}
|
|
return v
|
|
},
|
|
0
|
|
).slice(0, 500)
|
|
} catch {
|
|
json = '[unstringifiable]'
|
|
}
|
|
return { keys, json }
|
|
}
|
|
|
|
export function redactSocketEndpoint(endpoint: string): string {
|
|
try {
|
|
return new URL(endpoint).host || 'unknown'
|
|
} catch {
|
|
return 'unknown'
|
|
}
|
|
}
|