@fileverse-dev/ddoc 4.8.15 → 4.8.17-xchacha.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.
@@ -1,5 +1,5 @@
1
1
  import { Awareness } from 'y-protocols/awareness.js';
2
- import { SyncManagerConfig, CollabConnectionConfig, CollabServices, CollabCallbacks, CollabStatus, CollabState } from './types';
2
+ import { SyncManagerConfig, CollabConnectionConfig, CollabServices, CollabCallbacks, CollabStatus, CollabState, WireFormat } from './types';
3
3
 
4
4
  export declare class SyncManager {
5
5
  private onCollabStateChange;
@@ -26,10 +26,17 @@ export declare class SyncManager {
26
26
  private isProcessing;
27
27
  private syncId;
28
28
  private floor;
29
+ private hydrationIncomplete;
30
+ private wireFormat;
31
+ private lastReportedWriteFormat;
32
+ getWireFormat(): WireFormat;
33
+ private encryptForWire;
34
+ private emitWireTelemetry;
35
+ private setWireFormat;
29
36
  private updatesSinceSnapshot;
30
37
  private isAuthoringSnapshot;
31
38
  private readonly SNAPSHOT_THRESHOLD;
32
- private tailCompactTimer;
39
+ private deferredSnapshotTimer;
33
40
  private gapCatchUpTimer;
34
41
  private gapCatchUpInFlight;
35
42
  private gapCatchUpCooldownUntil;
@@ -100,6 +107,7 @@ export declare class SyncManager {
100
107
  private authorSnapshot;
101
108
  private hydrate;
102
109
  private maybeCompactTail;
110
+ private scheduleDeferredSnapshot;
103
111
  private initializeAwareness;
104
112
  private cleanupAwareness;
105
113
  private broadcastLocalContents;
@@ -1,6 +1,10 @@
1
+ import { WireFormat } from '../types';
2
+
3
+ export declare const WIRE_TAG = "FVXC1";
4
+ export declare const isXChaChaCipher: (message: unknown) => message is string;
1
5
  export declare const crypto: {
2
6
  generateKeyPair: () => import('@fileverse/crypto/ecies').EciesKeyPairBytes;
3
- encryptData: (key: Uint8Array, message: Uint8Array) => string;
4
- decryptData: (key: Uint8Array, message: string) => Uint8Array<ArrayBufferLike>;
7
+ encryptData: (key: Uint8Array, message: Uint8Array, format?: WireFormat) => string;
8
+ decryptData: (key: Uint8Array, message: string) => Uint8Array;
5
9
  generateRandomBytes: <E extends import('@fileverse/crypto/types').EncodingType = "bytes">(length?: number, encoding?: E) => import('@fileverse/crypto/types').EncodedReturnType<E>;
6
10
  };
@@ -1,2 +1,4 @@
1
- export declare const encryptForRoomKey: (roomKey: string, bytes: Uint8Array) => string;
1
+ import { WireFormat } from '../types';
2
+
3
+ export declare const encryptForRoomKey: (roomKey: string, bytes: Uint8Array, format?: WireFormat) => string;
2
4
  export declare const decryptForRoomKey: (roomKey: string, ciphertext: string) => Uint8Array;
@@ -6,3 +6,11 @@ export declare function shouldAuthorSnapshot(p: {
6
6
  threshold: number;
7
7
  }): boolean;
8
8
  export declare function computeLocalOnlyUpdate(ydoc: Y.Doc, serverMerged: Uint8Array | null): Uint8Array | null;
9
+ export declare function floorEligibleSeqs(rows: Array<{
10
+ seq: number | null;
11
+ isTail: boolean;
12
+ decrypted: boolean;
13
+ }>, alreadyIncomplete: boolean): {
14
+ seqs: number[];
15
+ incomplete: boolean;
16
+ };
@@ -1,4 +1,4 @@
1
- import { ISocketInitConfig, SocketStatusEnum, SendUpdateResponse, HydrationResponse, SnapshotResponse, AckResponse } from './types';
1
+ import { ISocketInitConfig, SocketStatusEnum, SendUpdateResponse, HydrationResponse, SnapshotResponse, AckResponse, WireFormat } from './types';
2
2
  import { Awareness } from 'y-protocols/awareness.js';
3
3
 
4
4
  interface ISocketClientConfig {
@@ -42,6 +42,7 @@ interface ISocketClientConfig {
42
42
  onHandshakeData?: (response: {
43
43
  data: AckResponse;
44
44
  roomKey: string;
45
+ wireFormat: WireFormat;
45
46
  }) => void;
46
47
  roomInfo?: {
47
48
  documentTitle: string;
@@ -80,6 +81,8 @@ export declare class SocketClient {
80
81
  private actorHandle?;
81
82
  private joinOnly?;
82
83
  private roomKey;
84
+ private wireFormat;
85
+ getWireFormat(): WireFormat;
83
86
  private roomInfo?;
84
87
  private awareness;
85
88
  private connectionAttemptErrorCount;
@@ -1,6 +1,25 @@
1
1
  import { Data, IDocCollabUsers } from '../../types';
2
2
 
3
3
  import * as Y from 'yjs';
4
+ /** Collab wire cipher. `ecies` is the historical secp256k1 ECIES; `xchacha` is
5
+ * XChaCha20-Poly1305 under an HKDF subkey of the roomKey (FVXC1). */
6
+ export type WireFormat = 'ecies' | 'xchacha';
7
+ /** Host telemetry for the wire migration; the package never imports a reporter. */
8
+ export type WireTelemetryEvent = {
9
+ type: 'announced';
10
+ format: WireFormat;
11
+ } | {
12
+ type: 'write';
13
+ format: WireFormat;
14
+ } | {
15
+ type: 'hydrate';
16
+ eciesRows: number;
17
+ xchachaRows: number;
18
+ snapshotFormat: WireFormat | null;
19
+ incomplete: boolean;
20
+ } | {
21
+ type: 'refused';
22
+ };
4
23
  /** Connection identity — changes to these trigger reconnect */
5
24
  export interface CollabConnectionConfig {
6
25
  roomKey: string;
@@ -150,7 +169,11 @@ export interface CollabCallbacks {
150
169
  onHandshakeData?: (data: {
151
170
  data: AckResponse;
152
171
  roomKey: string;
172
+ wireFormat: WireFormat;
153
173
  }) => void;
174
+ /** The write format the server announced for this room (auth ack or live ratchet). */
175
+ onWireFormat?: (format: WireFormat) => void;
176
+ onWireTelemetry?: (event: WireTelemetryEvent) => void;
154
177
  /** Live rename from the room owner; title is roomKey-encrypted. */
155
178
  onTitleUpdate?: (encryptedTitle: string | null) => void;
156
179
  /** Decrypt-miss self-heal: resolves the CURRENT-epoch roomKey (same resolution the host
@@ -195,7 +218,8 @@ export declare enum ServerErrorCode {
195
218
  INTERNAL_ERROR = "INTERNAL_ERROR",
196
219
  JOIN_DISABLED = "JOIN_DISABLED",
197
220
  EDIT_REVOKED = "EDIT_REVOKED",
198
- ROOM_NOT_ESTABLISHED = "ROOM_NOT_ESTABLISHED"
221
+ ROOM_NOT_ESTABLISHED = "ROOM_NOT_ESTABLISHED",
222
+ WIRE_FORMAT_UNSUPPORTED = "WIRE_FORMAT_UNSUPPORTED"
199
223
  }
200
224
  export interface AckResponse<T = Record<string, any>> {
201
225
  status: boolean;
@@ -260,6 +284,10 @@ export interface ISocketInitConfig {
260
284
  }) => void;
261
285
  onPresenceChange?: (collaborators: IDocCollabUsers[]) => void;
262
286
  onTitleUpdate?: (encryptedTitle: string | null) => void;
287
+ onWireFormat?: (data: {
288
+ roomId: string;
289
+ wireFormat: WireFormat;
290
+ }) => void;
263
291
  onSessionTerminated: (data: {
264
292
  roomId: string;
265
293
  }) => void;
@@ -289,4 +317,5 @@ export interface IAuthArgs {
289
317
  editUcan?: string;
290
318
  actorHandle?: string;
291
319
  joinOnly?: boolean;
320
+ wireFormats?: WireFormat[];
292
321
  }
@@ -1,7 +1,8 @@
1
1
  import { Awareness } from 'y-protocols/awareness';
2
2
  import { SocketClient } from '../socketClient';
3
+ import { WireFormat } from '../types';
3
4
 
4
- export declare const createAwarenessUpdateHandler: (awareness: Awareness, socketClient: SocketClient, roomKey: string) => ({ added, updated, removed, }: {
5
+ export declare const createAwarenessUpdateHandler: (awareness: Awareness, socketClient: SocketClient, roomKey: string, getWireFormat: () => WireFormat) => ({ added, updated, removed, }: {
5
6
  added: number[];
6
7
  updated: number[];
7
8
  removed: number[];
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@fileverse-dev/ddoc",
3
3
  "private": false,
4
4
  "description": "DDoc",
5
- "version": "4.8.15",
5
+ "version": "4.8.17-xchacha.0",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/fileverse/fileverse-ddocs.git"