@interncom/diplomatic 0.9.0 → 0.11.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.
@@ -0,0 +1,57 @@
1
+ import { Enclave } from "../shared/crypto/enclave";
2
+ import type { MasterSeed } from "../shared/types";
3
+ import type { ISeedStore, SetSeedOpts } from "../types";
4
+ export type LargeBlobRp = {
5
+ rpId?: string;
6
+ rpName?: string;
7
+ };
8
+ /** Best-effort capability probe (not all UAs expose this). */
9
+ export declare function largeBlobCapable(): Promise<boolean>;
10
+ export type LargeBlobCreateOpts = LargeBlobRp & {
11
+ userName?: string;
12
+ /**
13
+ * Omit (default) to allow both platform (Hello/Touch ID) and roaming
14
+ * authenticators (YubiKey). Set only if you intentionally restrict.
15
+ */
16
+ authenticatorAttachment?: AuthenticatorAttachment;
17
+ };
18
+ /**
19
+ * Create a discoverable credential with largeBlob support.
20
+ * Does not write the seed — call {@link writeLargeBlobSeed} next (second gesture).
21
+ *
22
+ * Default allows platform *and* cross-platform authenticators. Forcing
23
+ * `authenticatorAttachment: "platform"` excludes YubiKeys and similar.
24
+ */
25
+ export declare function createLargeBlobCred(opts?: LargeBlobCreateOpts): Promise<Uint8Array>;
26
+ /** Persist seed on an existing largeBlob-capable credential. */
27
+ export declare function writeLargeBlobSeed(credId: Uint8Array, seed: MasterSeed, opts?: LargeBlobRp): Promise<void>;
28
+ /** Overwrite largeBlob with 32 zero bytes (destroys stored seed material). UV required. */
29
+ export declare function clearLargeBlobSeed(credId: Uint8Array, opts?: LargeBlobRp): Promise<void>;
30
+ /** Read seed from largeBlob (user verification required). */
31
+ export declare function readLargeBlobSeed(credId: Uint8Array, opts?: LargeBlobRp): Promise<MasterSeed>;
32
+ /**
33
+ * Create credential and write seed (two user gestures).
34
+ * Returns credential id — persist it (e.g. IDB); the seed lives on the authenticator.
35
+ */
36
+ export declare function storeSeedLargeBlob(seed: MasterSeed, opts?: LargeBlobCreateOpts): Promise<Uint8Array>;
37
+ /**
38
+ * ISeedStore backed by largeBlob.
39
+ * - {@link save} creates (or reuses) cred + writes seed (gestures).
40
+ * - {@link load} returns in-memory enclave only; call {@link unlock} after restart.
41
+ * - Local {@link credId} must be persisted by the app across sessions.
42
+ * - {@link wipe} overwrites largeBlob with zeros (UV), then drops memory + credId.
43
+ * Does not delete the WebAuthn credential from the authenticator.
44
+ */
45
+ export declare class PasskeySeedStore implements ISeedStore {
46
+ #private;
47
+ constructor(opts?: LargeBlobRp & {
48
+ credId?: Uint8Array;
49
+ });
50
+ get credId(): Uint8Array | undefined;
51
+ setCredId(credId: Uint8Array | undefined): void;
52
+ save(seed: MasterSeed, opts?: SetSeedOpts): Promise<Enclave>;
53
+ load(): Promise<Enclave | void>;
54
+ /** User-gesture unlock after cold start (needs {@link credId}). */
55
+ unlock(): Promise<Enclave>;
56
+ wipe(): Promise<void>;
57
+ }
@@ -1,11 +1,15 @@
1
1
  import { Enclave } from "../../shared/crypto/enclave";
2
2
  import { MasterSeed } from "../../shared/types";
3
- import { ISeedStore } from "../../types";
3
+ import { ISeedStore, type SetSeedOpts } from "../../types";
4
4
  export declare class IDBSeedStore implements ISeedStore {
5
5
  enclave?: Enclave;
6
6
  db: IDBDatabase;
7
7
  constructor(db: IDBDatabase);
8
- save(seed: MasterSeed): Promise<Enclave>;
8
+ save(seed: MasterSeed, opts?: SetSeedOpts): Promise<Enclave>;
9
9
  load(): Promise<Enclave | undefined>;
10
+ /**
11
+ * Explicit identity clear only. Not invoked by {@link IDBStore.wipe}
12
+ * (that deletes the whole protocol DB, including legacy seedMeta).
13
+ */
10
14
  wipe(): Promise<void>;
11
15
  }
@@ -18,6 +18,7 @@ export declare const MESSAGES_TABLE = "messages";
18
18
  export declare const MESSAGES_APLD_INDEX = "apld";
19
19
  /** Schema version: v3 adds messages.apld index for the apply queue. */
20
20
  export declare const DIPLOMATIC_STORE_DB_VERSION = 3;
21
+ export declare const DIPLOMATIC_STORE_DB_NAME = "diplomatic-store-db";
21
22
  export declare class IDBStore implements IStore<URL> {
22
23
  seed: IDBSeedStore;
23
24
  hosts: IDBHostStore;
@@ -26,8 +27,11 @@ export declare class IDBStore implements IStore<URL> {
26
27
  messages: IDBMessageStore;
27
28
  db: IDBDatabase;
28
29
  constructor(db: IDBDatabase, crypto: ICrypto);
30
+ /**
31
+ * Clear protocol tables only (not seed). Seed is wiped only via
32
+ * {@link ISeedStore.wipe} when client.wipe({ seed: true }).
33
+ */
29
34
  wipe(): Promise<void>;
30
35
  }
31
- export declare const DIPLOMATIC_STORE_DB_NAME = "diplomatic-store-db";
32
36
  export declare function openIDBStoreDB(): Promise<IDBDatabase>;
33
37
  export declare function openIDBStore(crypto: ICrypto): Promise<IDBStore>;
@@ -1,9 +1,9 @@
1
1
  import { Enclave } from "../../shared/crypto/enclave";
2
2
  import { MasterSeed } from "../../shared/types";
3
- import { ISeedStore } from "../../types";
3
+ import { ISeedStore, type SetSeedOpts } from "../../types";
4
4
  export declare class MemorySeedStore implements ISeedStore {
5
5
  enclave?: Enclave;
6
- save(seed: MasterSeed): Promise<Enclave>;
6
+ save(seed: MasterSeed, _opts?: SetSeedOpts): Promise<Enclave>;
7
7
  load(): Promise<Enclave | undefined>;
8
8
  wipe(): Promise<void>;
9
9
  }
@@ -29,9 +29,43 @@ export type Applier = (ops: IOp[]) => Promise<{
29
29
  types: Set<string>;
30
30
  eids: EntityID[];
31
31
  }>;
32
+ /** Options for loading a seed into the enclave. */
33
+ export type SetSeedOpts = {
34
+ /**
35
+ * When true, write seed to the durable store (e.g. IndexedDB).
36
+ * Default false (memory only) — IDB is readable by other local apps.
37
+ * Opt in only when the app accepts that tradeoff (or has no better store).
38
+ */
39
+ persist?: boolean;
40
+ };
41
+ /**
42
+ * Selective wipe for {@link IClient.wipe}.
43
+ *
44
+ * Default `client.wipe()` / `client.wipe({})` clears **everything except seed**:
45
+ * msgs, ents, meta = true; seed = false.
46
+ * That avoids passkey/largeBlob UV when the user only wants to clear app data.
47
+ * Pass `{ seed: true }` to also clear identity (may prompt the authenticator).
48
+ */
49
+ export type WipeOpts = {
50
+ /** Message archive. Default true. */
51
+ msgs?: boolean;
52
+ /** Application EntDB / state manager. Default true. */
53
+ ents?: boolean;
54
+ /** Hosts + upload/download queues. Default true. */
55
+ meta?: boolean;
56
+ /**
57
+ * Seed / identity ({@link ISeedStore.wipe}). Default **false**.
58
+ * When true, passkey stores overwrite largeBlob (UV ceremony).
59
+ */
60
+ seed?: boolean;
61
+ };
32
62
  export interface ISeedStore {
33
- save: (seed: MasterSeed) => Promise<Enclave>;
63
+ save: (seed: MasterSeed, opts?: SetSeedOpts) => Promise<Enclave>;
34
64
  load: () => Promise<Enclave | void>;
65
+ /**
66
+ * Clear durable seed material for this store (IDB row, largeBlob overwrite, …)
67
+ * and drop the in-memory enclave. Called only when client.wipe({ seed: true }).
68
+ */
35
69
  wipe: () => Promise<void>;
36
70
  }
37
71
  export interface IHostRow<Handle extends HostHandle> extends IHostConnectionInfo<Handle>, Partial<IHostMetadata> {
@@ -239,6 +273,9 @@ export interface IStore<Handle extends HostHandle> {
239
273
  uploads: IUploadQueue;
240
274
  downloads: IDownloadQueue;
241
275
  messages: IMessageStore;
276
+ /**
277
+ * Clear protocol tables (hosts, queues, messages). Does not call seed.wipe.
278
+ */
242
279
  wipe(): Promise<void>;
243
280
  }
244
281
  type UnlistenFunc = () => void;
@@ -248,7 +285,7 @@ export interface IStateEmitter<T> {
248
285
  listen(listener: (state: T) => void): UnlistenFunc;
249
286
  }
250
287
  export interface IClient<Handle extends HostHandle> {
251
- setSeed(seed: MasterSeed): Promise<void>;
288
+ setSeed(seed: MasterSeed, opts?: SetSeedOpts): Promise<void>;
252
289
  link(host: IHostConnectionInfo<Handle>): Promise<void>;
253
290
  unlink(label: string): Promise<void>;
254
291
  /** Linked hosts from the protocol store (handle, label, lastSeq, …). */
@@ -298,7 +335,11 @@ export interface IClient<Handle extends HostHandle> {
298
335
  * on the host row.
299
336
  */
300
337
  reconcile(hostLabel: string, opts?: ReconcileOpts): Promise<ValStat<ReconcileReport>>;
301
- wipe(): Promise<void>;
338
+ /**
339
+ * Clear local state. Defaults wipe msgs/ents/meta only; seed requires
340
+ * `{ seed: true }` (avoids passkey UV on ordinary EXIT / data wipe).
341
+ */
342
+ wipe(opts?: WipeOpts): Promise<void>;
302
343
  import(file: File): Promise<Status>;
303
344
  export(filename: string, extension?: string): Promise<Status>;
304
345
  clientState: IStateEmitter<IDiplomaticClientState>;
@@ -2,7 +2,7 @@ import { IClock } from "../shared/clock";
2
2
  import { Status } from "../shared/consts";
3
3
  import type { EntityID, Hash, IDeleteParams, IEntRev, IHostConnectionInfo, IInsertParams, IMessageHead, IStateManager, IUpdateParams, MasterSeed, SerializedContent } from "../shared/types";
4
4
  import { type ValStat } from "../shared/valstat";
5
- import type { ApldState, IClient, IDiplomaticClientState, IDiplomaticClientXferState, IHostRow, IStateEmitter, IStore, IStoredMessage, ListMsgsOpts, ReconcileOpts, ReconcileReport } from "../types";
5
+ import type { ApldState, IClient, IDiplomaticClientState, IDiplomaticClientXferState, IHostRow, IStateEmitter, IStore, IStoredMessage, ListMsgsOpts, ReconcileOpts, ReconcileReport, SetSeedOpts, WipeOpts } from "../types";
6
6
  /**
7
7
  * Options for attaching to an app-owned sync Worker.
8
8
  *
@@ -37,6 +37,8 @@ export type WorkerClientOptions = {
37
37
  export declare class WorkerClient implements IClient<URL> {
38
38
  private worker;
39
39
  private state;
40
+ /** Shared protocol store (main connection). */
41
+ private store;
40
42
  /** Main-thread writer: msg archive + local apply for fast UI. */
41
43
  private local;
42
44
  private nextId;
@@ -98,7 +100,7 @@ export declare class WorkerClient implements IClient<URL> {
98
100
  private request;
99
101
  private requestStatus;
100
102
  private serializeHost;
101
- setSeed(seed: MasterSeed): Promise<void>;
103
+ setSeed(seed: MasterSeed, opts?: SetSeedOpts): Promise<void>;
102
104
  link(host: IHostConnectionInfo<URL>, connect?: boolean): Promise<void>;
103
105
  unlink(label: string): Promise<void>;
104
106
  /** Hosts live in shared main IDB (same as local writer). */
@@ -131,7 +133,7 @@ export declare class WorkerClient implements IClient<URL> {
131
133
  * SyncClient has no EntDB; use entDB.checksum(crypto) on the main path.
132
134
  */
133
135
  entcheck(): Promise<Hash>;
134
- wipe(): Promise<void>;
136
+ wipe(opts?: WipeOpts): Promise<void>;
135
137
  import(file: File): Promise<Status>;
136
138
  export(filename: string, _extension?: string): Promise<Status>;
137
139
  }
@@ -14,6 +14,7 @@ export type WorkerCmd = {
14
14
  id: number;
15
15
  op: "setSeed";
16
16
  seed: Uint8Array;
17
+ persist?: boolean;
17
18
  } | {
18
19
  id: number;
19
20
  op: "link";
@@ -54,6 +55,10 @@ export type WorkerCmd = {
54
55
  } | {
55
56
  id: number;
56
57
  op: "wipe";
58
+ msgs?: boolean;
59
+ ents?: boolean;
60
+ meta?: boolean;
61
+ seed?: boolean;
57
62
  } | {
58
63
  id: number;
59
64
  op: "import";