@interncom/diplomatic 0.21.1 → 0.23.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.
Files changed (84) hide show
  1. package/dist/cli/bun/src/crypto.d.ts +2 -3
  2. package/dist/cli/index.mjs +4 -5
  3. package/dist/cli/shared/api/peek.d.ts +9 -1
  4. package/dist/cli/shared/api/pull.d.ts +9 -1
  5. package/dist/cli/shared/api/push.d.ts +3 -1
  6. package/dist/cli/shared/api/user.d.ts +1 -1
  7. package/dist/cli/shared/bag.d.ts +7 -4
  8. package/dist/cli/shared/client.d.ts +10 -4
  9. package/dist/cli/shared/codecs/kdm.d.ts +6 -0
  10. package/dist/cli/shared/codecs/notifItem.d.ts +2 -0
  11. package/dist/cli/shared/crypto/derivation.d.ts +45 -0
  12. package/dist/cli/shared/crypto/enclave.d.ts +40 -61
  13. package/dist/cli/shared/crypto/largeBlob.d.ts +8 -0
  14. package/dist/cli/shared/crypto/noble.d.ts +15 -22
  15. package/dist/cli/shared/crypto/pairing.d.ts +8 -4
  16. package/dist/cli/shared/crypto/prf.d.ts +52 -0
  17. package/dist/cli/shared/crypto/realms.d.ts +7 -0
  18. package/dist/cli/shared/endpoint.d.ts +2 -2
  19. package/dist/cli/shared/http.d.ts +12 -12
  20. package/dist/cli/shared/sync.d.ts +4 -2
  21. package/dist/cli/shared/types.d.ts +24 -11
  22. package/dist/cli/shared/webauthn/prf.d.ts +8 -0
  23. package/dist/cli/src/index.d.ts +5 -4
  24. package/dist/web/client.d.ts +10 -5
  25. package/dist/web/crypto.d.ts +2 -3
  26. package/dist/web/entdb/cached.d.ts +4 -0
  27. package/dist/web/entdb/entdb.d.ts +3 -0
  28. package/dist/web/entdb/idb.d.ts +9 -4
  29. package/dist/web/index.d.ts +11 -5
  30. package/dist/web/index.mjs +1 -1
  31. package/dist/web/passkey/prf-store.d.ts +26 -10
  32. package/dist/web/passkey/seed.d.ts +12 -6
  33. package/dist/web/shared/api/peek.d.ts +9 -1
  34. package/dist/web/shared/api/pull.d.ts +9 -1
  35. package/dist/web/shared/api/push.d.ts +3 -1
  36. package/dist/web/shared/api/user.d.ts +1 -1
  37. package/dist/web/shared/bag.d.ts +7 -4
  38. package/dist/web/shared/client.d.ts +10 -4
  39. package/dist/web/shared/codecs/kdm.d.ts +6 -0
  40. package/dist/web/shared/codecs/notifItem.d.ts +2 -0
  41. package/dist/web/shared/crypto/derivation.d.ts +45 -0
  42. package/dist/web/shared/crypto/enclave.d.ts +40 -61
  43. package/dist/web/shared/crypto/largeBlob.d.ts +8 -0
  44. package/dist/web/shared/crypto/noble.d.ts +15 -22
  45. package/dist/web/shared/crypto/pairing.d.ts +8 -4
  46. package/dist/web/shared/crypto/prf.d.ts +52 -0
  47. package/dist/web/shared/crypto/realms.d.ts +7 -0
  48. package/dist/web/shared/crypto/tty.d.ts +3 -0
  49. package/dist/web/shared/endpoint.d.ts +2 -2
  50. package/dist/web/shared/http.d.ts +12 -12
  51. package/dist/web/shared/storage/memory.d.ts +2 -2
  52. package/dist/web/shared/sync.d.ts +4 -2
  53. package/dist/web/shared/types.d.ts +24 -11
  54. package/dist/web/shared/webauthn/prf.d.ts +8 -0
  55. package/dist/web/stores/cursor.d.ts +30 -0
  56. package/dist/web/stores/idb/account.d.ts +58 -0
  57. package/dist/web/stores/idb/catalog.d.ts +1 -0
  58. package/dist/web/stores/idb/dnlds.d.ts +3 -2
  59. package/dist/web/stores/idb/hosts.d.ts +8 -7
  60. package/dist/web/stores/idb/idbutil.d.ts +2 -0
  61. package/dist/web/stores/idb/migrate.d.ts +2 -0
  62. package/dist/web/stores/idb/msgs.d.ts +1 -1
  63. package/dist/web/stores/idb/names.d.ts +13 -0
  64. package/dist/web/stores/idb/realms.d.ts +11 -0
  65. package/dist/web/stores/idb/store.d.ts +26 -19
  66. package/dist/web/stores/idb/uplds.d.ts +1 -1
  67. package/dist/web/stores/keyTag.d.ts +14 -0
  68. package/dist/web/stores/label.d.ts +3 -0
  69. package/dist/web/stores/memory/account.d.ts +14 -0
  70. package/dist/web/stores/memory/dnlds.d.ts +4 -2
  71. package/dist/web/stores/memory/hosts.d.ts +8 -6
  72. package/dist/web/stores/memory/realms.d.ts +10 -0
  73. package/dist/web/stores/memory/store.d.ts +6 -2
  74. package/dist/web/stores/realm.d.ts +35 -0
  75. package/dist/web/sync.d.ts +14 -11
  76. package/dist/web/types.d.ts +52 -16
  77. package/dist/web/worker/client.d.ts +1 -1
  78. package/dist/web/worker/protocol.d.ts +6 -0
  79. package/dist/web/worker/runtime.d.ts +4 -2
  80. package/dist/web/worker.mjs +1 -1
  81. package/package.json +1 -1
  82. package/dist/web/stores/idb/seed.d.ts +0 -32
  83. package/dist/web/stores/identityPin.d.ts +0 -19
  84. package/dist/web/stores/memory/seed.d.ts +0 -13
@@ -0,0 +1,6 @@
1
+ import { ICodecStruct } from "../codec.ts";
2
+ export interface IKDM {
3
+ label: string;
4
+ index: number;
5
+ }
6
+ export declare const kdmCodec: ICodecStruct<IKDM>;
@@ -1,6 +1,8 @@
1
1
  import { ICodecStruct } from "../codec.ts";
2
+ import { type HostRlm } from "../crypto/derivation.ts";
2
3
  export interface IBagNotifItem {
3
4
  seq: number;
5
+ rlm: HostRlm;
4
6
  headCph: Uint8Array;
5
7
  bodyCph?: Uint8Array;
6
8
  }
@@ -0,0 +1,45 @@
1
+ import { type IKDM } from "../codecs/kdm.ts";
2
+ import { type ValStat } from "../valstat.ts";
3
+ export declare const Purpose: {
4
+ readonly Identity: "diplomatic.identity.v1";
5
+ readonly Cipher: "diplomatic.cipher.v1";
6
+ readonly Bind: "diplomatic.bind.v1";
7
+ readonly BindTag: "diplomatic.bindtag.v1";
8
+ readonly Fingerprint: "diplomatic.fingerprint.v1";
9
+ readonly Pair: "diplomatic.qrpair.v1";
10
+ readonly BagKdm: "diplomatic.bagkdm.v1";
11
+ readonly RealmKey: "diplomatic.realmKey.v1";
12
+ readonly RealmID: "diplomatic.realmID.v1";
13
+ readonly HostRLM: "diplomatic.hostRLM.v1";
14
+ };
15
+ export type Purpose = typeof Purpose[keyof typeof Purpose];
16
+ declare const pdkSymbol: unique symbol;
17
+ export type PurposeDerivedKey<P extends Purpose> = Uint8Array & {
18
+ readonly [pdkSymbol]: P;
19
+ };
20
+ declare const childKeySymbol: unique symbol;
21
+ export type ChildKey<P extends Purpose> = Uint8Array & {
22
+ readonly [childKeySymbol]: P;
23
+ };
24
+ export type PDK = {
25
+ [K in keyof typeof Purpose]: ChildKey<(typeof Purpose)[K]>;
26
+ };
27
+ /** Host-stamped bag rlm. Peek, pull, and bag signatures use this. */
28
+ export type HostRlm = PDK["HostRLM"];
29
+ export declare const nullKDM: IKDM;
30
+ export declare function asChildKey<P extends Purpose>(bytes: Uint8Array, _purpose: P): ValStat<ChildKey<P>>;
31
+ export declare function asHostRlm(bytes: Uint8Array): ValStat<HostRlm>;
32
+ export declare function derivePDK<P extends Purpose>({ parent, purpose, }: {
33
+ parent: Uint8Array;
34
+ purpose: P;
35
+ }): Promise<ValStat<PurposeDerivedKey<P>>>;
36
+ export declare function deriveChild<P extends Purpose>({ pdk, kdm, }: {
37
+ pdk: PurposeDerivedKey<P>;
38
+ kdm: Uint8Array | IKDM;
39
+ }): Promise<ValStat<ChildKey<P>>>;
40
+ export declare function deriveKey<P extends Purpose>({ parent, purpose, kdm, }: {
41
+ parent: Uint8Array;
42
+ purpose: P;
43
+ kdm: Uint8Array | IKDM;
44
+ }): Promise<ValStat<ChildKey<P>>>;
45
+ export {};
@@ -1,43 +1,18 @@
1
1
  import type { BundleHost } from "../codecs/bundleHost.ts";
2
+ import type { IKDM } from "../codecs/kdm.ts";
2
3
  import { Status } from "../consts.ts";
3
- import { MASTER_SEED_LEN, type MasterSeed, type SealedMasterKey } from "../seed.ts";
4
- import type { ICrypto, PublicKey } from "../types.ts";
4
+ import { type MasterSeed, type SealedMasterKey } from "../seed.ts";
5
+ import type { PublicKey } from "../types.ts";
5
6
  import { type ValStat } from "../valstat.ts";
7
+ import { type HostRlm, type PDK } from "./derivation.ts";
6
8
  import { type DHKEReq, type DHKEResp, PairRequest } from "./pairing.ts";
7
9
  import { type LargeBlobCreateOpts, type LargeBlobRp } from "../webauthn/largeBlob.ts";
8
- import { type PrfCeremony, type PrfCreateOpts, type PrfEvalOpts, type PrfRp } from "../webauthn/prf.ts";
9
- export type { LargeBlobCreateOpts, LargeBlobRp };
10
- export type { PrfCreateOpts, PrfEvalOpts, PrfRp };
11
- /** Options for PRF seal/unseal ceremonies (no raw PRF bytes). */
12
- export type PasskeyPrfOpts = PrfCreateOpts & {
13
- credId?: Uint8Array | readonly Uint8Array[];
14
- /** Seal only: create a PRF credential first when no credId is known. */
15
- createCredIfNeeded?: boolean;
16
- };
17
- /** One binding to try on unseal (cred id + sealed master). */
18
- export type PrfBinding = {
19
- sealedMaster: SealedMasterKey;
20
- credId: Uint8Array;
21
- };
22
- /** Durable PRF-sealed master + public ceremony facts (never includes PRF output). */
23
- export type PrfSealedMaster = PrfCeremony & {
24
- sealedMaster: SealedMasterKey;
25
- salt: Uint8Array;
26
- };
27
- /** One existing keyring member used to prove this enclave matches the list. */
28
- export type BindPrior = {
29
- credId: Uint8Array;
30
- tag: Uint8Array;
31
- };
32
- /** Seal + bind-tag from {@link Enclave.bind} (tag is not a global fingerprint). */
33
- export type PrfBound = PrfSealedMaster & {
34
- tag: Uint8Array;
35
- };
10
+ import { type BindPrior, type PasskeyPrfOpts, type PrfBinding, type PrfBound, type PrfSealedMaster } from "./prf.ts";
36
11
  export type EncryptCipher = {
37
- encrypt: (data: Uint8Array) => Promise<Uint8Array>;
12
+ encrypt: (data: Uint8Array) => Promise<ValStat<Uint8Array>>;
38
13
  };
39
14
  export type DecryptCipher = {
40
- decrypt: (data: Uint8Array) => Promise<Uint8Array>;
15
+ decrypt: (data: Uint8Array) => Promise<ValStat<Uint8Array>>;
41
16
  };
42
17
  /** Encrypt + decrypt capability for one KDM. */
43
18
  export type DerivedCipher = EncryptCipher & DecryptCipher;
@@ -50,21 +25,21 @@ export type CipherForUsage<U extends CipherUsage> = {
50
25
  both: DerivedCipher;
51
26
  }[U];
52
27
  /**
53
- * Path-scoped signing identity: public key is public; sign/kdmFor re-enter
28
+ * KDM-scoped signing identity: public key is public; sign/kdmFor re-enter
54
29
  * the enclave so the private key never leaves. Used for hosts, export files, etc.
55
30
  */
56
31
  export type Identity = {
57
32
  readonly publicKey: PublicKey;
58
- sign: (message: Uint8Array | string) => Promise<Uint8Array>;
59
- /** Per-bag KDM mixed with this identity's private key (see bag seal). */
60
- kdmFor: (msgHeadEnc: Uint8Array) => Promise<Uint8Array>;
33
+ sign: (message: Uint8Array | string) => Promise<ValStat<Uint8Array>>;
34
+ /** Per-bag 8-byte KDM (bag-kdm PDK child keyed by the encoded head). */
35
+ kdmFor: (msgHeadEnc: Uint8Array) => Promise<ValStat<Uint8Array>>;
61
36
  };
62
- declare const SEAL_BIND_DOMAIN: Uint8Array<ArrayBufferLike>;
63
- declare const FP_MODE: Uint8Array<ArrayBufferLike>;
64
- declare const SEAL_KEY_LEN = 32;
65
- declare const SEAL_PRF_MIN_LEN = 16;
66
37
  /** Minimum musec length (Mandatory User-Space Entropy Contribution). */
67
- declare const MUSEC_MIN_LEN = 32;
38
+ export declare const MUSEC_MIN_LEN = 32;
39
+ export declare function fromSeedHosts(buf: Uint8Array): ValStat<{
40
+ enclave: Enclave;
41
+ hosts: BundleHost[];
42
+ }>;
68
43
  /** Brand `bytes` as {@link MasterSeed} only if length is {@link MASTER_SEED_LEN}. */
69
44
  export declare function asMasterSeed(bytes: Uint8Array): ValStat<MasterSeed>;
70
45
  export declare class Enclave {
@@ -90,7 +65,7 @@ export declare class Enclave {
90
65
  */
91
66
  sealWithPasskey(opts?: PasskeyPrfOpts): Promise<ValStat<PrfSealedMaster>>;
92
67
  /**
93
- * UV + PRF seal, plus a per-cred bind tag (blake3(master ‖ domain ‖ credId)).
68
+ * UV + PRF seal, plus a per-cred bind tag (bindtag PDK child keyed by credId).
94
69
  * Tag compute and compare stay in the enclave. If `prior` is non-empty, every
95
70
  * stored tag must match this master or bind fails (one keyring, one master).
96
71
  */
@@ -117,8 +92,8 @@ export declare class Enclave {
117
92
  static unsealWithIkm(sealed: SealedMasterKey, ikm: Uint8Array): Promise<ValStat<Enclave>>;
118
93
  /**
119
94
  * UV + write IdentityBundle (seed + hosts) to largeBlob.
120
- * Encode and WebAuthn write complete inside this method; nothing seed-bearing
121
- * is returned. Prefer empty `hosts` for seed-only backup.
95
+ * Encode stays here; {@link writeLargeBlob} does the UV write. Nothing
96
+ * seed-bearing is returned. Prefer empty `hosts` for seed-only backup.
122
97
  *
123
98
  * Pass `opts.credId` to write an existing credential (one UV). Omit it to
124
99
  * create a largeBlob-capable credential then write (two UV). Returns the
@@ -149,16 +124,19 @@ export declare class Enclave {
149
124
  * Web bundles set DIP_CLI_DUMP=false; the write is compiled out.
150
125
  */
151
126
  dumpToTty(): Promise<Status>;
127
+ static pairRequest(): Promise<ValStat<PairRequest>>;
152
128
  /**
153
- * Absorb seed‖hosts plaintext (pair AEAD inner).
154
- * Encoder/Decoder never see the seed.
129
+ * Seals seed+hosts for dhkeReq. Returns dhkeResp to send back.
130
+ * @param acks Set fields only after explicit user affirmation (e.g. a checkbox).
131
+ * Do not default these to `true` in application code.
155
132
  */
156
- static fromPairPlain(plain: Uint8Array): ValStat<{
157
- enclave: Enclave;
158
- hosts: BundleHost[];
159
- }>;
160
- static pairRequest(): Promise<ValStat<PairRequest>>;
161
- pairAccept(dhkeReq: DHKEReq, hosts: BundleHost[]): Promise<ValStat<DHKEResp>>;
133
+ pairAccept(dhkeReq: DHKEReq, hosts: BundleHost[], acks: {
134
+ /**
135
+ * Set `true` only after the user explicitly affirms they control both
136
+ * devices in this pair. Never hard-code in a client.
137
+ */
138
+ userControlsBothSidesOfPair: true;
139
+ }): Promise<ValStat<DHKEResp>>;
162
140
  /**
163
141
  * Spawn a new sync Worker from the embedded bundle and inject this enclave's
164
142
  * master seed into it (transfer). Seed never goes to a caller-supplied port —
@@ -171,18 +149,19 @@ export declare class Enclave {
171
149
  id: number;
172
150
  persist?: boolean;
173
151
  }): Worker;
152
+ realmID(realmKDM: IKDM): Promise<ValStat<PDK["RealmID"]>>;
153
+ hostRlm(realmKDM: IKDM, hostKDM: IKDM): Promise<ValStat<PDK["HostRLM"]>>;
154
+ realmForRlm(hostKDM: IKDM, rlm: HostRlm, realms: readonly IKDM[]): Promise<ValStat<IKDM>>;
174
155
  /**
175
- * Cipher for public KDM. Does not hold key bytes; each op re-enters the
176
- * enclave (async, hardware-shaped). `usage` selects the return shape:
156
+ * Cipher for public KDM under a realm (default: nullKDM). Does not hold
157
+ * key bytes; each op re-enters the enclave. `usage` selects the shape:
177
158
  * `"encrypt"` → `{ encrypt }`, `"decrypt"` → `{ decrypt }`, `"both"` → both.
178
159
  */
179
- deriveCipher<U extends CipherUsage>(kdm: Uint8Array, usage: U): CipherForUsage<U>;
160
+ deriveCipher<U extends CipherUsage>(kdm: Uint8Array, usage: U, realmKDM?: IKDM): CipherForUsage<U>;
180
161
  /**
181
- * Path-scoped identity (label+index). Private key stays in the enclave; only
182
- * publicKey and capability methods are returned (frozen).
162
+ * Identity from the identity PDK + KDM. Private key stays in the enclave;
163
+ * only publicKey and capability methods are returned.
183
164
  */
184
- deriveIdentity(keyPath: string, idx?: number): Promise<Identity>;
165
+ deriveIdentity(kdm: IKDM): Promise<ValStat<Identity>>;
166
+ fingerprint(kdm?: Uint8Array | IKDM): Promise<ValStat<PDK["Fingerprint"]>>;
185
167
  }
186
- /** Derive seal key from PRF output (domain-separated). Used by enclave seal/unseal. */
187
- export declare function sealKeyFromPrf(crypto: ICrypto, prf: Uint8Array, domain?: Uint8Array): Promise<ValStat<Uint8Array>>;
188
- export { FP_MODE, MASTER_SEED_LEN, MUSEC_MIN_LEN, SEAL_BIND_DOMAIN, SEAL_KEY_LEN, SEAL_PRF_MIN_LEN, };
@@ -0,0 +1,8 @@
1
+ import { Status } from "../consts.ts";
2
+ import { type ValStat } from "../valstat.ts";
3
+ import { type LargeBlobCreateOpts, type LargeBlobRp } from "../webauthn/largeBlob.ts";
4
+ export declare function largeBlobCredId(opts?: LargeBlobCreateOpts & {
5
+ credId?: Uint8Array;
6
+ }): Promise<ValStat<Uint8Array>>;
7
+ export declare function writeLargeBlob(credId: Uint8Array, data: Uint8Array, opts?: LargeBlobRp): Promise<Status>;
8
+ export declare function wipeLargeBlob(credId: Uint8Array, opts?: LargeBlobRp): Promise<Status>;
@@ -1,24 +1,17 @@
1
1
  import { type X25519Sk } from "./x25519.ts";
2
2
  import type { Blake3Opts, DerivationSeed, Hash, ICrypto, KeyPair } from "../types.ts";
3
- /**
4
- * ICrypto: noble for XSalsa20 + blake3; WebCrypto Ed25519 + X25519
5
- * (our scalar; RFC 7748 check before trusting pub/DH).
6
- */
7
- export declare class NobleCrypto implements ICrypto {
8
- private verifyKeys;
9
- genRandomBytes(bytes: number): Promise<Uint8Array>;
10
- gen256BitSecureRandomSeed(): Promise<Uint8Array>;
11
- encryptXSalsa20Poly1305Combined(data: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
12
- decryptXSalsa20Poly1305Combined(data: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
13
- deriveEd25519KeyPair(derivationSeed: DerivationSeed): Promise<KeyPair>;
14
- private importSignKey;
15
- private importVerifyKey;
16
- signEd25519(message: Uint8Array | string, secKey: Uint8Array): Promise<Uint8Array>;
17
- checkSigEd25519(sig: Uint8Array, message: Uint8Array | string, pubKey: Uint8Array): Promise<boolean>;
18
- blake3(data: Uint8Array, opts?: Blake3Opts): Promise<Hash>;
19
- genX25519(): Promise<{
20
- priv: X25519Sk;
21
- pub: Uint8Array;
22
- }>;
23
- x25519Shared(priv: X25519Sk, peerPub: Uint8Array): Promise<Uint8Array>;
24
- }
3
+ export declare function genRandomBytes(bytes: number): Promise<Uint8Array>;
4
+ export declare function gen256BitSecureRandomSeed(): Promise<Uint8Array>;
5
+ export declare function encryptXSalsa20Poly1305Combined(data: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
6
+ export declare function decryptXSalsa20Poly1305Combined(data: Uint8Array, key: Uint8Array): Promise<Uint8Array>;
7
+ export declare function deriveEd25519KeyPair(derivationSeed: DerivationSeed): Promise<KeyPair>;
8
+ export declare function importVerifyKey(pubKey: Uint8Array): Promise<CryptoKey>;
9
+ export declare function signEd25519(message: Uint8Array | string, secKey: Uint8Array): Promise<Uint8Array>;
10
+ export declare function checkSigEd25519(sig: Uint8Array, message: Uint8Array | string, verifyKey: CryptoKey): Promise<boolean>;
11
+ export declare function blake3(data: Uint8Array, opts?: Blake3Opts): Promise<Hash>;
12
+ export declare function genX25519(): Promise<{
13
+ priv: X25519Sk;
14
+ pub: Uint8Array;
15
+ }>;
16
+ export declare function x25519Shared(priv: X25519Sk, peerPub: Uint8Array): Promise<Uint8Array>;
17
+ export declare const noble: ICrypto;
@@ -1,8 +1,8 @@
1
1
  import type { BundleHost } from "../codecs/bundleHost.ts";
2
2
  import { type ValStat } from "../valstat.ts";
3
- import { Enclave } from "./enclave.ts";
3
+ import { type PDK } from "./derivation.ts";
4
+ import type { Enclave } from "./enclave.ts";
4
5
  import type { X25519Sk } from "./x25519.ts";
5
- export declare const SEAL_PAIR_DOMAIN: Uint8Array<ArrayBufferLike>;
6
6
  export declare const X25519_PUB_LEN = 32;
7
7
  /** respPub (32) ‖ XSalsa nonce (24) ‖ tag (16); plaintext follows in the ct. */
8
8
  export declare const DHKE_RESP_MIN: number;
@@ -19,13 +19,17 @@ export declare function asDHKEResp(bytes: Uint8Array): ValStat<DHKEResp>;
19
19
  export declare function pairKey(sk: X25519Sk, // local X25519 priv
20
20
  peer: Uint8Array, // ECDH peer pub (enroller: dhkeReq; enrollee: respPub)
21
21
  reqPub: Uint8Array, // enrollee pub, bound into KDF
22
- respPub: Uint8Array): Promise<ValStat<Uint8Array>>;
22
+ respPub: Uint8Array): Promise<ValStat<PDK["Pair"]>>;
23
+ export declare function sealPair(dhkeReq: DHKEReq): Promise<ValStat<{
24
+ key: PDK["Pair"];
25
+ pub: Uint8Array;
26
+ }>>;
23
27
  export declare class PairRequest {
24
28
  #private;
25
29
  private constructor();
26
30
  static create(): Promise<ValStat<PairRequest>>;
27
31
  wipe(): void;
28
- get dhkeReq(): DHKEReq;
32
+ dhkeReq(): ValStat<DHKEReq>;
29
33
  finish(dhkeResp: DHKEResp): Promise<ValStat<{
30
34
  enclave: Enclave;
31
35
  hosts: BundleHost[];
@@ -0,0 +1,52 @@
1
+ import type { SealedMasterKey } from "../seed.ts";
2
+ import { type ValStat } from "../valstat.ts";
3
+ import { type PDK } from "./derivation.ts";
4
+ import { type PrfCeremony, type PrfCreateOpts, type PrfEvalOpts } from "../webauthn/prf.ts";
5
+ /** Options for PRF seal/unseal ceremonies (no raw PRF bytes). */
6
+ export type PasskeyPrfOpts = PrfCreateOpts & {
7
+ credId?: Uint8Array | readonly Uint8Array[];
8
+ /** Seal only: create a PRF credential first when no credId is known. */
9
+ createCredIfNeeded?: boolean;
10
+ };
11
+ /** One binding to try on unseal (cred id + sealed master). */
12
+ export type PrfBinding = {
13
+ sealedMaster: SealedMasterKey;
14
+ credId: Uint8Array;
15
+ /** PRF salt for this cred. Omitted salts use the ceremony salt. */
16
+ salt?: Uint8Array;
17
+ };
18
+ /** Durable PRF-sealed master + public ceremony facts (never includes PRF output). */
19
+ export type PrfSealedMaster = PrfCeremony & {
20
+ sealedMaster: SealedMasterKey;
21
+ salt: Uint8Array;
22
+ };
23
+ /** One existing keyring member used to prove this enclave matches the list. */
24
+ export type BindPrior = {
25
+ credId: Uint8Array;
26
+ tag: PDK["BindTag"];
27
+ };
28
+ /** Seal + bind-tag from {@link Enclave.bind} (tag is not a global fingerprint). */
29
+ export type PrfBound = PrfSealedMaster & {
30
+ tag: PDK["BindTag"];
31
+ };
32
+ type PrfCreateResult = PrfCeremony & {
33
+ prfEnabled: boolean;
34
+ prf?: Uint8Array;
35
+ };
36
+ type PrfEvalResult = PrfCeremony & {
37
+ prf: Uint8Array;
38
+ };
39
+ export declare function createPrfCred(opts?: PrfCreateOpts): Promise<ValStat<PrfCreateResult>>;
40
+ export declare function evalPrf(opts?: PrfEvalOpts): Promise<ValStat<PrfEvalResult>>;
41
+ export declare function sealPRF(opts: PasskeyPrfOpts | undefined): Promise<ValStat<PrfCeremony & {
42
+ prf: Uint8Array;
43
+ salt: Uint8Array;
44
+ }>>;
45
+ export declare function unsealPRF(bindings: readonly PrfBinding[], opts: PasskeyPrfOpts & {
46
+ salt: Uint8Array;
47
+ }): Promise<ValStat<{
48
+ prf: Uint8Array;
49
+ credId: Uint8Array;
50
+ order: readonly PrfBinding[];
51
+ }>>;
52
+ export {};
@@ -0,0 +1,7 @@
1
+ import { type IKDM } from "../codecs/kdm.ts";
2
+ import { type MasterSeed } from "../seed.ts";
3
+ import { type ValStat } from "../valstat.ts";
4
+ import { type PDK } from "./derivation.ts";
5
+ export declare function deriveRealmKey(parent: MasterSeed, realmKDM: IKDM): Promise<ValStat<PDK["RealmKey"]>>;
6
+ export declare function deriveRealmID(parent: MasterSeed, realmKDM: IKDM): Promise<ValStat<PDK["RealmID"]>>;
7
+ export declare function deriveHostRLM(parent: PDK["RealmID"], hostKDM: IKDM): Promise<ValStat<PDK["HostRLM"]>>;
@@ -10,8 +10,8 @@ interface IProtoClient {
10
10
  enclave: Enclave;
11
11
  clock: IClock;
12
12
  }
13
- export interface IAuthenticatedEndpoint<ReqItem, Resp> {
14
- encodeReq(client: IProtoClient, identity: Identity, authTS: IAuthTimestamp, body: Iterable<ReqItem>, reqEnc: Encoder): Promise<Status>;
13
+ export interface IAuthenticatedEndpoint<ReqInput, Resp> {
14
+ encodeReq(client: IProtoClient, identity: Identity, authTS: IAuthTimestamp, body: ReqInput, reqEnc: Encoder): Promise<Status>;
15
15
  handleReq(host: IProtoHost, reqDec: Decoder, respEnc: Encoder): Promise<Status>;
16
16
  decodeResp(respDec: Decoder): ValStat<Resp>;
17
17
  }
@@ -6,66 +6,66 @@ import { ValStat } from "./valstat.ts";
6
6
  export declare const api: {
7
7
  readonly user: {
8
8
  readonly path: "/user";
9
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<never, void>;
9
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<void, void>;
10
10
  readonly name: APICallName.User;
11
11
  };
12
12
  readonly push: {
13
13
  readonly path: "/push";
14
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./types.ts").IBag, import("./codecs/pushItem.ts").IBagPushItem[]>;
14
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./types.ts").IBag[], import("./codecs/pushItem.ts").IBagPushItem[]>;
15
15
  readonly name: APICallName.Push;
16
16
  };
17
17
  readonly peek: {
18
18
  readonly path: "/peek";
19
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<number, import("./codecs/peekItem.ts").IBagPeekItem[]>;
19
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./api/peek.ts").IPeekCursor, import("./codecs/peekItem.ts").IBagPeekItem[]>;
20
20
  readonly name: APICallName.Peek;
21
21
  };
22
22
  readonly pull: {
23
23
  readonly path: "/pull";
24
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<number, import("./codecs/pullItem.ts").IBagPullItem[]>;
24
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./api/pull.ts").IPullReq, import("./codecs/pullItem.ts").IBagPullItem[]>;
25
25
  readonly name: APICallName.Pull;
26
26
  };
27
27
  };
28
28
  export declare const apiCalls: {
29
29
  readonly 0: {
30
30
  readonly path: "/user";
31
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<never, void>;
31
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<void, void>;
32
32
  readonly name: APICallName.User;
33
33
  };
34
34
  readonly 2: {
35
35
  readonly path: "/push";
36
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./types.ts").IBag, import("./codecs/pushItem.ts").IBagPushItem[]>;
36
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./types.ts").IBag[], import("./codecs/pushItem.ts").IBagPushItem[]>;
37
37
  readonly name: APICallName.Push;
38
38
  };
39
39
  readonly 1: {
40
40
  readonly path: "/peek";
41
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<number, import("./codecs/peekItem.ts").IBagPeekItem[]>;
41
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./api/peek.ts").IPeekCursor, import("./codecs/peekItem.ts").IBagPeekItem[]>;
42
42
  readonly name: APICallName.Peek;
43
43
  };
44
44
  readonly 3: {
45
45
  readonly path: "/pull";
46
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<number, import("./codecs/pullItem.ts").IBagPullItem[]>;
46
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./api/pull.ts").IPullReq, import("./codecs/pullItem.ts").IBagPullItem[]>;
47
47
  readonly name: APICallName.Pull;
48
48
  };
49
49
  };
50
50
  export declare const callPaths: {
51
51
  readonly "/user": {
52
52
  readonly path: "/user";
53
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<never, void>;
53
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<void, void>;
54
54
  readonly name: APICallName.User;
55
55
  };
56
56
  readonly "/push": {
57
57
  readonly path: "/push";
58
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./types.ts").IBag, import("./codecs/pushItem.ts").IBagPushItem[]>;
58
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./types.ts").IBag[], import("./codecs/pushItem.ts").IBagPushItem[]>;
59
59
  readonly name: APICallName.Push;
60
60
  };
61
61
  readonly "/peek": {
62
62
  readonly path: "/peek";
63
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<number, import("./codecs/peekItem.ts").IBagPeekItem[]>;
63
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./api/peek.ts").IPeekCursor, import("./codecs/peekItem.ts").IBagPeekItem[]>;
64
64
  readonly name: APICallName.Peek;
65
65
  };
66
66
  readonly "/pull": {
67
67
  readonly path: "/pull";
68
- readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<number, import("./codecs/pullItem.ts").IBagPullItem[]>;
68
+ readonly endpoint: import("./endpoint.ts").IAuthenticatedEndpoint<import("./api/pull.ts").IPullReq, import("./codecs/pullItem.ts").IBagPullItem[]>;
69
69
  readonly name: APICallName.Pull;
70
70
  };
71
71
  };
@@ -1,9 +1,11 @@
1
1
  import { IBagPeekItem } from "./codecs/peekItem.ts";
2
+ import type { IKDM } from "./codecs/kdm.ts";
3
+ import { type HostRlm } from "./crypto/derivation.ts";
2
4
  import { Enclave } from "./crypto/enclave.ts";
3
- import { ICrypto, PublicKey } from "./types.ts";
5
+ import { ICrypto } from "./types.ts";
4
6
  import { ValStat } from "./valstat.ts";
5
7
  export interface IDecryptedBagPeekItem {
6
8
  kdm: Uint8Array;
7
9
  headEnc: Uint8Array;
8
10
  }
9
- export declare function decryptPeekItem(item: IBagPeekItem, pubKey: PublicKey, enclave: Enclave, crypto: ICrypto): Promise<ValStat<IDecryptedBagPeekItem>>;
11
+ export declare function decryptPeekItem(item: IBagPeekItem, verifyKey: CryptoKey, enclave: Enclave, crypto: ICrypto, rlm: HostRlm, realm?: IKDM): Promise<ValStat<IDecryptedBagPeekItem>>;
@@ -4,6 +4,7 @@ import { IAuthTimestamp } from "./codecs/authTimestamp.ts";
4
4
  import type { IBagPeekItem } from "./codecs/peekItem.ts";
5
5
  import { IUsageQuota } from "./codecs/usageQuota.ts";
6
6
  import { APICallName, Status } from "./consts.ts";
7
+ import type { HostRlm } from "./crypto/derivation.ts";
7
8
  import type { ValStat } from "./valstat.ts";
8
9
  /** Identity seed brands — defined in seed.ts; re-exported for convenience. */
9
10
  export type { MasterSeed, SealedMasterKey } from "./seed.ts";
@@ -75,27 +76,35 @@ export type IDeleteParams = {
75
76
  eid: EntityID;
76
77
  force?: boolean;
77
78
  };
79
+ /** One setBags outcome. Success carries the host seq in that bag's rlm. */
80
+ export type ISetBagResult = {
81
+ status: Status.Success;
82
+ seq: number;
83
+ } | {
84
+ status: Exclude<Status, Status.Success>;
85
+ };
78
86
  export interface IStorage {
79
87
  addUser: (pubKey: PublicKey) => Promise<ValStat<void>>;
80
88
  hasUser: (pubKey: PublicKey) => Promise<ValStat<boolean>>;
81
89
  subMeta: (pubKey: PublicKey) => Promise<ValStat<ISubscriptionMetadata>>;
82
90
  /**
83
- * Store bags for a user. Returns host seq for each bag in order.
84
- * Empty list succeeds with []. Implementations must assign contiguous
85
- * seqs atomically (transaction / single batch) so concurrent writers
86
- * cannot claim the same seq.
91
+ * Store bags for a user. One result per input bag, same order.
92
+ * An invalid rlm is InvalidParam for that bag; the others are still stored.
93
+ * Seqs are contiguous per rlm among stored bags, assigned atomically so
94
+ * concurrent writers cannot claim the same seq in the same rlm.
95
+ * Empty list succeeds with []. A storage failure fails the call.
87
96
  */
88
- setBags: (pubKey: PublicKey, bags: IBag[]) => Promise<ValStat<number[]>>;
97
+ setBags: (pubKey: PublicKey, bags: IBag[]) => Promise<ValStat<ISetBagResult[]>>;
89
98
  /**
90
- * Fetch ciphertext bodies for the given host seqs.
91
- * Returns only seqs that exist (missing seqs are omitted, not an error).
92
- * Empty `seqs` succeeds with [].
99
+ * Fetch ciphertext bodies for `seqs` in `rlm`.
100
+ * Missing seqs are omitted. Empty `seqs` succeeds with [].
93
101
  */
94
- getBodies: (pubKey: PublicKey, seqs: number[]) => Promise<ValStat<{
102
+ getBodies: (pubKey: PublicKey, rlm: HostRlm, seqs: number[]) => Promise<ValStat<{
95
103
  seq: number;
96
104
  bodyCph: Uint8Array;
97
105
  }[]>>;
98
- listHeads: (pubKey: PublicKey, minSeq: number) => Promise<ValStat<IBagPeekItem[]>>;
106
+ /** Heads in `rlm` with seq greater than minSeq, ordered by seq. */
107
+ listHeads: (pubKey: PublicKey, rlm: HostRlm, minSeq: number) => Promise<ValStat<IBagPeekItem[]>>;
99
108
  }
100
109
  export interface KeyPair {
101
110
  keyType: "ed25519";
@@ -123,7 +132,8 @@ export type Hash = Uint8Array & {
123
132
  readonly [hashSymbol]: true;
124
133
  };
125
134
  export interface IHostCrypto {
126
- checkSigEd25519: (sig: Uint8Array, message: Uint8Array | string, pubKey: PublicKey) => Promise<boolean>;
135
+ importVerifyKey: (pubKey: PublicKey) => Promise<CryptoKey>;
136
+ checkSigEd25519: (sig: Uint8Array, message: Uint8Array | string, verifyKey: CryptoKey) => Promise<boolean>;
127
137
  }
128
138
  /** BLAKE3 hash / MAC / KDF (noble: `key` XOR `context`, not both). */
129
139
  export type Blake3Opts = {
@@ -168,6 +178,9 @@ export interface IPushListener {
168
178
  disconnect(): void;
169
179
  }
170
180
  export interface IBagHeader {
181
+ /** HostRLM. Covered by sig, with headCph. */
182
+ rlm: HostRlm;
183
+ /** Ed25519 over rlm ‖ headCph. First field on the wire. */
171
184
  sig: Uint8Array;
172
185
  kdm: Uint8Array;
173
186
  }
@@ -29,6 +29,14 @@ export type PrfEvalOpts = PrfRp & {
29
29
  /** One id, or every bound id so a spare key can assert in one get(). */
30
30
  credId?: Uint8Array | readonly Uint8Array[];
31
31
  salt?: Uint8Array;
32
+ /**
33
+ * Salt for each cred when accounts do not share one.
34
+ * Sent as evalByCredential so the passkey the user picks evals its own.
35
+ */
36
+ salts?: readonly {
37
+ credId: Uint8Array;
38
+ salt: Uint8Array;
39
+ }[];
32
40
  };
33
41
  /** Best-effort: client advertises PRF extension. */
34
42
  export declare function prfCapable(): Promise<boolean>;
@@ -3,6 +3,7 @@ import { IClock } from "../shared/clock.ts";
3
3
  import type { IBagPeekItem } from "../shared/codecs/peekItem.ts";
4
4
  import { IBagPullItem } from "../shared/codecs/pullItem.ts";
5
5
  import { IBagPushItem } from "../shared/codecs/pushItem.ts";
6
+ import type { IKDM } from "../shared/codecs/kdm.ts";
6
7
  import { Status } from "../shared/consts.ts";
7
8
  import { Enclave } from "../shared/crypto/enclave.ts";
8
9
  import { HostHandle, IHostConnectionInfo, IMessage, ITransport } from "../shared/types.ts";
@@ -16,10 +17,10 @@ export declare class CLIClient<Handle extends HostHandle> {
16
17
  clock?: IClock;
17
18
  });
18
19
  connect(host: IHostConnectionInfo<Handle>, transport: ITransport): Promise<Status>;
19
- push(msgs: IMessage[]): Promise<ValStat<IBagPushItem[]>>;
20
- peek(lastSeq: number): Promise<ValStat<IBagPeekItem[]>>;
21
- pull(seqs: number[]): Promise<ValStat<IBagPullItem[]>>;
22
- open(peekItem: IBagPeekItem, pullItem: IBagPullItem): Promise<ValStat<IOpenBag>>;
20
+ push(msgs: IMessage[], realm?: IKDM): Promise<ValStat<IBagPushItem[]>>;
21
+ peek(lastSeq: number, realm?: IKDM): Promise<ValStat<IBagPeekItem[]>>;
22
+ pull(seqs: number[], realm?: IKDM): Promise<ValStat<IBagPullItem[]>>;
23
+ open(peekItem: IBagPeekItem, pullItem: IBagPullItem, realm?: IKDM): Promise<ValStat<IOpenBag>>;
23
24
  upsertSingletonSync(type: string, body: Uint8Array): Promise<Status>;
24
25
  listen(onNotification: (bytes: Uint8Array) => Promise<Status>, onDisconnect?: () => void, onConnect?: () => void): Promise<Status>;
25
26
  isConnected(): boolean;
@@ -5,8 +5,9 @@ import { EncodedMessage } from "./shared/message";
5
5
  import type { Enclave } from "./shared/crypto/enclave";
6
6
  import { EntityID, Hash, HostHandle, ICrypto, IDeleteParams, IEntRev, IHostConnectionInfo, IInsertParams, IMessageHead, IStateManager, ITransport, IUpdateParams } from "./shared/types";
7
7
  import { ValStat } from "./shared/valstat";
8
- import { ApldState, IClient, IDiplomaticClientState, IDiplomaticClientXferState, IHostRow, IStateEmitter, IStore, IStoredMessage, ListMsgsOpts, ReconcileOpts, ReconcileReport, SetSeedOpts, WipeOpts } from "./types";
8
+ import { ApldState, IClient, IDiplomaticClientState, IDiplomaticClientXferState, IHostRow, IStateEmitter, IStore, IStoredMessage, ListMsgsOpts, OpenAccount, ReconcileOpts, ReconcileReport, SetSeedOpts, WipeOpts } from "./types";
9
9
  export declare class SyncClient<Handle extends HostHandle> implements IClient<Handle> {
10
+ #private;
10
11
  private clock;
11
12
  private state;
12
13
  private store;
@@ -56,7 +57,10 @@ export declare class SyncClient<Handle extends HostHandle> implements IClient<Ha
56
57
  onScheduleSync?: (() => void) | undefined);
57
58
  /** Record phase progress and notify xferState listeners. */
58
59
  private emitProgress;
59
- setSeed(enclave: Enclave, opts?: SetSeedOpts): Promise<void>;
60
+ /** Account this client is operating as, if one is open. */
61
+ selected(): OpenAccount<Handle> | undefined;
62
+ setSeed(enclave: Enclave, opts?: SetSeedOpts): Promise<Status>;
63
+ adopt(enclave: Enclave, label?: string): Promise<Status>;
60
64
  private getClientState;
61
65
  private getXferState;
62
66
  /**
@@ -168,9 +172,10 @@ export declare class SyncClient<Handle extends HostHandle> implements IClient<Ha
168
172
  /** Count archive rows; optional apld filter. Prefer over list+length. */
169
173
  countMsgs(apld?: ApldState): Promise<number>;
170
174
  /**
171
- * Full inventory of one host (peek seq 0): advances lastSeq; optionally
172
- * enqueues pull/push. Waits out in-flight {@link sync} first (same as
173
- * {@link rebuild}). By default drains via {@link sync}, then re-inventories.
175
+ * Full inventory of one host (peek seq 0 per realm). Sets each cursor and
176
+ * optionally enqueues pull/push. Waits out in-flight {@link sync} first
177
+ * (same as {@link rebuild}). By default drains via {@link sync}, then
178
+ * re-inventories.
174
179
  * Returns ephemeral {@link ReconcileReport} (msgcheck, numBags, numDupes) —
175
180
  * bag tallies are not persisted.
176
181
  */
@@ -1,3 +1,2 @@
1
- import { NobleCrypto } from "./shared/crypto/noble";
2
- declare const crypto: NobleCrypto;
3
- export default crypto;
1
+ import { noble } from "./shared/crypto/noble";
2
+ export default noble;