ping-openmls-sdk-react-native-macos 0.7.5 → 0.7.6

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.
@@ -146,6 +146,15 @@ RCT_EXTERN_METHOD(consumeLinkingTicket: (NSDictionary *)ticket
146
146
  resolver: (RCTPromiseResolveBlock)resolve
147
147
  rejecter: (RCTPromiseRejectBlock)reject)
148
148
 
149
+ // [CR-3] HPKE-open a sealed LinkingTicket on the new device. Free
150
+ // function (not on the client instance) — the new device is pre-init
151
+ // and doesn't have a MessagingClient yet at the time of the open call.
152
+ // Returns the same dict shape `consumeLinkingTicket` accepts as input.
153
+ RCT_EXTERN_METHOD(openLinkingTicket: (NSArray *)sealed
154
+ newDevicePriv: (NSArray *)newDevicePriv
155
+ resolver: (RCTPromiseResolveBlock)resolve
156
+ rejecter: (RCTPromiseRejectBlock)reject)
157
+
149
158
  RCT_EXTERN_METHOD(revokeDevice: (NSArray *)deviceId
150
159
  nowMs: (double)nowMs
151
160
  resolver: (RCTPromiseResolveBlock)resolve
@@ -684,6 +684,31 @@ public final class PingNative: RCTEventEmitter {
684
684
  }
685
685
  }
686
686
 
687
+ /// HPKE-open a sealed `LinkingTicket` on the new device ([CR-3]).
688
+ /// Free function (not on `client`) — the new device is pre-init and
689
+ /// doesn't have a `MessagingClient` yet when the open happens. Mirrors
690
+ /// the wasm SDK's `MessagingClient.openLinkingTicket(sealed, priv)`
691
+ /// static so the desktop link host can decode the ticket before
692
+ /// calling `init` + `consumeLinkingTicket`.
693
+ @objc(openLinkingTicket:newDevicePriv:resolver:rejecter:)
694
+ public func openLinkingTicketNative(
695
+ _ sealedBytes: NSArray,
696
+ newDevicePriv newDevicePrivBytes: NSArray,
697
+ resolver resolve: @escaping RCTPromiseResolveBlock,
698
+ rejecter reject: @escaping RCTPromiseRejectBlock
699
+ ) {
700
+ do {
701
+ let sealed = try TypeBridge.decodeBytesOrThrow(sealedBytes, field: "sealed")
702
+ let priv = try TypeBridge.decodeBytesOrThrow(newDevicePrivBytes, field: "newDevicePriv")
703
+ // `open_linking_ticket` is a UniFFI top-level free function;
704
+ // Swift exposes it camelCased.
705
+ let ticket = try openLinkingTicket(sealed: sealed, newDevicePriv: priv)
706
+ resolve(TypeBridge.encodeLinkingTicket(ticket))
707
+ } catch {
708
+ reject("OpenLinkingFailed", String(describing: error), error)
709
+ }
710
+ }
711
+
687
712
  /// Revoke a device ([CR-2]). Returns the array of Commit envelopes the SDK
688
713
  /// produced — one per conversation the device was a locally-known leaf in.
689
714
  /// Empty array means the device wasn't locally known (scope limit per CR-2).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ping-openmls-sdk-react-native-macos",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Real MLS for React Native macOS apps — wraps the ping-openmls-sdk Rust core via UniFFI.",
5
5
  "homepage": "https://github.com/AMP-Media-Development/ping-openmls-sdk",
6
6
  "license": "Apache-2.0",
@@ -373,6 +373,33 @@ export class MessagingClient {
373
373
  await NativePing.consumeLinkingTicket(encodeLinkingTicket(ticket), Date.now());
374
374
  }
375
375
 
376
+ /**
377
+ * [CR-3] HPKE-open a sealed linking ticket on the new device. Static —
378
+ * the new device hasn't initialised a `MessagingClient` yet at the
379
+ * time of the open call (it does `openLinkingTicket` first to extract
380
+ * the auth-layer fields, hands them to `/v1/auth/link-verify` to
381
+ * mint tokens, THEN `init`s and `consumeLinkingTicket`s).
382
+ *
383
+ * Mirrors the wasm SDK's `MessagingClient.openLinkingTicket` so the
384
+ * desktop link host can share code shape with the web link host.
385
+ *
386
+ * @param sealed - HPKE-sealed bytes from `getLinkingTicket(ticketId)`
387
+ * (the BE relays exactly what the existing device
388
+ * `sealLinkingTicket`'d).
389
+ * @param newDevicePriv - 32-byte X25519 private key the new device
390
+ * generated for this pairing session.
391
+ */
392
+ static async openLinkingTicket(
393
+ sealed: Uint8Array,
394
+ newDevicePriv: Uint8Array,
395
+ ): Promise<LinkingTicket> {
396
+ const raw = await NativePing.openLinkingTicket(
397
+ Array.from(sealed),
398
+ Array.from(newDevicePriv),
399
+ );
400
+ return decodeLinkingTicket(raw);
401
+ }
402
+
376
403
  /**
377
404
  * Admit a freshly-linked device to every chat in `entries` — one Commit +
378
405
  * Welcome per chat, with per-chat outcomes. Host calls this AFTER
package/src/NativePing.ts CHANGED
@@ -200,6 +200,19 @@ export interface Spec extends TurboModule {
200
200
  nowMs: number,
201
201
  ): Promise<null>;
202
202
 
203
+ /**
204
+ * [CR-3] HPKE-open a sealed linking ticket on the new device. Free
205
+ * function — runs BEFORE `initClient` so the host can decode the
206
+ * ticket fields (`user_pubkey`, `new_device_id`, `device_binding_sig`)
207
+ * and submit them to the auth layer's `/v1/auth/link-verify` before
208
+ * spinning up the messaging client. Returns the same dict shape
209
+ * `consumeLinkingTicket` accepts.
210
+ */
211
+ openLinkingTicket(
212
+ sealed: number[],
213
+ newDevicePriv: number[],
214
+ ): Promise<Record<string, unknown>>;
215
+
203
216
  /**
204
217
  * Revoke a device ([CR-2]). Returns one Commit envelope per conversation the
205
218
  * device was a locally-known leaf in. Empty array means the device wasn't locally