@muhkoo/connect 0.6.0-alpha.1 → 0.6.0-alpha.11

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.
package/dist/connect.d.ts CHANGED
@@ -1812,6 +1812,16 @@ interface AuthSuccess {
1812
1812
  token: string;
1813
1813
  username: string;
1814
1814
  }
1815
+ /** A vault factor record (M1.0). Wrap/iv are base64 AES-GCM; absent for phrase. */
1816
+ interface VaultFactor {
1817
+ id: string;
1818
+ type: "password" | "passkey" | "phrase-marker";
1819
+ wrap?: string;
1820
+ iv?: string;
1821
+ params?: Record<string, unknown>;
1822
+ label?: string;
1823
+ createdAt?: number;
1824
+ }
1815
1825
  interface AuthClientOptions {
1816
1826
  /** Absolute URL of the accelerator worker (no trailing slash required). */
1817
1827
  baseUrl: string;
@@ -1836,6 +1846,28 @@ declare class AuthClient {
1836
1846
  verify(token: string): Promise<{
1837
1847
  username: string;
1838
1848
  }>;
1849
+ /** Blinded OPRF evaluation — the server-gated half of a password/recovery wrap key. */
1850
+ oprfEvaluate(username: string, blinded: string): Promise<{
1851
+ evaluated: string;
1852
+ }>;
1853
+ /** Read a factor record for `username` (returns an indistinguishable decoy if absent). */
1854
+ vaultRead(username: string, factorType: VaultFactor["type"]): Promise<{
1855
+ factor: VaultFactor | null;
1856
+ }>;
1857
+ /** Add/replace a factor (session-authed; the seed is already wrapped client-side). */
1858
+ vaultPutFactor(token: string, factor: VaultFactor): Promise<{
1859
+ ok: boolean;
1860
+ id: string;
1861
+ }>;
1862
+ /** List the user's factor metadata (no ciphertext). Session-authed. */
1863
+ vaultFactors(token: string): Promise<{
1864
+ factors: VaultFactor[];
1865
+ migrated: boolean;
1866
+ }>;
1867
+ /** Remove a factor by id (can't remove the last one). Session-authed. */
1868
+ vaultDeleteFactor(token: string, id: string): Promise<{
1869
+ deleted: boolean;
1870
+ }>;
1839
1871
  private json;
1840
1872
  private parse;
1841
1873
  }
@@ -1882,6 +1914,23 @@ interface ZkIdentity {
1882
1914
  * devices.
1883
1915
  */
1884
1916
  declare function deriveIdentity(username: string, password: string): Promise<ZkIdentity>;
1917
+ /**
1918
+ * Legacy master-seed derivation: `PBKDF2(password, "muhkoo-zk-v1:"||username)`.
1919
+ *
1920
+ * This was the *only* path pre-vault, where the identity descended directly from
1921
+ * the password. It's kept so existing accounts still re-derive their seed (and
1922
+ * the vault can adopt that exact seed on migration, preserving the commitment).
1923
+ * New accounts use a random seed (`vault.randomSeed`) instead, so their identity
1924
+ * is no longer a function of the password.
1925
+ */
1926
+ declare function deriveMasterSeedFromPassword(username: string, password: string): Promise<Uint8Array>;
1927
+ /**
1928
+ * Derive the (unchanged) ZK identity from a 32-byte **master seed**. The seed is
1929
+ * HKDF-expanded into secret/salt + the P-256 ECDSA & ECDH keypairs exactly as
1930
+ * before — so the resulting commitment is byte-identical for a given seed. The
1931
+ * vault wraps THIS seed under each recovery factor.
1932
+ */
1933
+ declare function deriveIdentityFromSeed(seed: Uint8Array): Promise<ZkIdentity>;
1885
1934
 
1886
1935
  /**
1887
1936
  * Poseidon hash wrapper used by the ZK auth flow.
@@ -2083,6 +2132,10 @@ declare function defaultSessionStore(keyPrefix?: string): SessionStore;
2083
2132
  declare class SessionState {
2084
2133
  private session;
2085
2134
  private _identity;
2135
+ /** The 32-byte master seed, in-memory only (never persisted). Held after
2136
+ * login/register so additional recovery factors (passkey, phrase) can be
2137
+ * enrolled, and a password can be changed, without re-deriving. */
2138
+ private _seed;
2086
2139
  private readonly store;
2087
2140
  constructor(store?: SessionStore);
2088
2141
  /** True once a token-bearing session exists (regardless of identity). */
@@ -2099,6 +2152,10 @@ declare class SessionState {
2099
2152
  setSession(session: StoredSession): Promise<void>;
2100
2153
  /** Attach derived identity material to the current session. */
2101
2154
  setIdentity(identity: ZkIdentity): void;
2155
+ /** The in-memory master seed (or null when locked / not held). */
2156
+ get seed(): Uint8Array | null;
2157
+ /** Hold the master seed in memory (set on login/register when available). */
2158
+ setSeed(seed: Uint8Array | null): void;
2102
2159
  /** Load a persisted session (used by `restore()`); identity stays null. */
2103
2160
  loadPersisted(): Promise<StoredSession | null>;
2104
2161
  /** Drop all session + identity state and clear persistence. */
@@ -2122,6 +2179,17 @@ declare class SessionState {
2122
2179
  * at-rest encryption and the messaging ratchet without re-deriving.
2123
2180
  */
2124
2181
 
2182
+ /**
2183
+ * Thrown when the identity vault can't be reached to unlock the seed — a network
2184
+ * failure, a 5xx, or the per-user rate limit (429). This is distinct from a wrong
2185
+ * password, and is surfaced so `login`/`unlock` do NOT silently fall back to the
2186
+ * legacy password derivation (which, for a vault account, yields a misleading
2187
+ * "commitment mismatch"). Callers should ask the user to retry, not re-enter a
2188
+ * password.
2189
+ */
2190
+ declare class VaultUnavailableError extends Error {
2191
+ constructor(cause?: unknown);
2192
+ }
2125
2193
  /** What the auth methods resolve to — the stable, non-secret user facts. */
2126
2194
  interface AuthUser {
2127
2195
  username: string;
@@ -2152,17 +2220,26 @@ declare class ZkAuth {
2152
2220
  private readonly deps;
2153
2221
  constructor(deps: ZkAuthDeps);
2154
2222
  /**
2155
- * Register a new user, then (by default) sign them in. The identity is
2156
- * derived deterministically from `(username, password)` — the same inputs
2157
- * reproduce it on any device, so there's no key material to ship around.
2223
+ * Register a new user, then (by default) sign them in.
2224
+ *
2225
+ * M1.0: the identity now descends from a **random master seed** (not the
2226
+ * password), so it's recoverable + the password can be changed. We register
2227
+ * the commitment, sign in with the in-memory identity to get a token, then
2228
+ * enroll the OPRF-gated **password factor** (the seed wrapped under a key the
2229
+ * server can't derive offline). Future logins unlock the seed via that factor.
2158
2230
  */
2159
2231
  register(params: RegisterParams): Promise<AuthUser>;
2160
2232
  /**
2161
- * Sign in: re-derive the identity, prove knowledge of it against a fresh
2162
- * server challenge, and trade the proof for a session token. On success
2163
- * both the session and the identity are stored on the client.
2233
+ * Sign in. M1.0 is **vault-first**: read the password factor and OPRF-unwrap
2234
+ * the master seed → identity. If that fails (a pre-vault account, whose factor
2235
+ * is absent so the server returns a decoy, or a wrong password), fall back to
2236
+ * the legacy password-derived identity. Either way we then prove knowledge of
2237
+ * the identity and trade it for a session token.
2164
2238
  */
2165
2239
  login(username: string, password: string, opts?: LoginOptions): Promise<AuthUser>;
2240
+ /** Enroll the password factor for a legacy (pre-vault) account. Idempotent +
2241
+ * best-effort; failure just means we retry on the next login. */
2242
+ private migrateLegacyPasswordFactor;
2166
2243
  /**
2167
2244
  * Silently re-authenticate the current user without prompting for a
2168
2245
  * password. Only possible while the client is **unlocked** — i.e. the
@@ -2200,6 +2277,60 @@ declare class ZkAuth {
2200
2277
  * the password by checking the derived commitment matches the session's.
2201
2278
  */
2202
2279
  unlock(password: string): Promise<void>;
2280
+ /**
2281
+ * Generate a 24-word **recovery phrase** that encodes the master seed, and
2282
+ * record a marker in the vault so the UI knows one exists. Show the returned
2283
+ * phrase to the user ONCE — it's never stored server-side (the phrase *is* the
2284
+ * seed). Requires being signed in (the seed must be held in memory).
2285
+ */
2286
+ enrollRecoveryPhrase(): Promise<string>;
2287
+ /**
2288
+ * Recover an account with its recovery phrase (the "forgot password" path).
2289
+ * Decodes the phrase to the master seed → identity → session. After this,
2290
+ * call {@link changePassword} to set a new password. No server lookup needed.
2291
+ */
2292
+ recoverWithPhrase(username: string, mnemonic: string, opts?: LoginOptions): Promise<AuthUser>;
2293
+ /**
2294
+ * Change the password — re-wraps the (unchanged) master seed under the new
2295
+ * password's OPRF-gated key. The identity/commitment never moves. Requires
2296
+ * being signed in (or freshly recovered) so the seed is held.
2297
+ */
2298
+ changePassword(newPassword: string): Promise<void>;
2299
+ /** Whether this browser can use passkeys (WebAuthn) at all. */
2300
+ passkeyAvailable(): boolean;
2301
+ /**
2302
+ * Whether this browser's authenticator can do the **PRF extension** our
2303
+ * passkey factor requires. A browser may support passkeys generally but not
2304
+ * PRF — in which case enrolling one would fail. Resolves `true`/`false`, or
2305
+ * `null` when it can't be determined (no capabilities API). Use this to gate
2306
+ * the passkey UI so users don't hit a dead-end error.
2307
+ */
2308
+ passkeyPrfAvailable(): Promise<boolean | null>;
2309
+ /**
2310
+ * Add a **passkey** recovery factor. Creates a WebAuthn passkey with PRF,
2311
+ * wraps the master seed under its PRF output, and stores the factor. The
2312
+ * passkey (synced via the platform's keychain) then unlocks the account on
2313
+ * any device — no password. Requires being signed in (seed held in memory).
2314
+ */
2315
+ enrollPasskey(opts?: {
2316
+ rpId?: string;
2317
+ rpName?: string;
2318
+ label?: string;
2319
+ }): Promise<void>;
2320
+ /**
2321
+ * Sign in with a passkey (no password). Reads the passkey factor, evaluates
2322
+ * its PRF, unwraps the master seed → identity → session.
2323
+ */
2324
+ loginWithPasskey(username: string, opts?: LoginOptions): Promise<AuthUser>;
2325
+ /** List the user's enrolled login methods (metadata only). Session-authed. */
2326
+ listFactors(): Promise<Array<{
2327
+ id: string;
2328
+ type: string;
2329
+ label?: string;
2330
+ createdAt?: number;
2331
+ }>>;
2332
+ /** Remove a login method by id (can't remove your only one). Session-authed. */
2333
+ removeFactor(id: string): Promise<void>;
2203
2334
  /** Sign out: clears the session, identity, and persisted token. */
2204
2335
  logout(): Promise<void>;
2205
2336
  /** The signed-in user, or `null`. Synchronous read of current state. */
@@ -2213,8 +2344,43 @@ declare class ZkAuth {
2213
2344
  get identity(): ZkIdentity | null;
2214
2345
  /** The current session token, or `null` when signed out. */
2215
2346
  get token(): string | null;
2347
+ /**
2348
+ * The master seed as base64, or `null` when locked. The host app uses this to
2349
+ * wrap app-level data (e.g. chat ratchet keys) to the **seed** instead of the
2350
+ * password — so that data survives password changes and can be unlocked by a
2351
+ * passwordless (passkey) login, both of which recover the same seed.
2352
+ */
2353
+ get seedBase64(): string | null;
2216
2354
  /** Poseidon commitment for an identity — the value the server stores. */
2217
2355
  private commitmentFor;
2356
+ /**
2357
+ * Derive the OPRF-gated wrap key for the password factor: `scrypt(password)`
2358
+ * is blinded, evaluated by the server's secret OPRF key (so it can't be
2359
+ * derived offline), unblinded, then HKDF'd into an AES-GCM key.
2360
+ */
2361
+ private passwordWrapKey;
2362
+ /**
2363
+ * Try to recover the master seed from the password factor.
2364
+ *
2365
+ * Returns `null` only when the vault read SUCCEEDS but the seed can't be
2366
+ * unwrapped — i.e. there's no real factor (a pre-vault/legacy account, whose
2367
+ * read returns a decoy that won't unwrap) or the password is wrong. The caller
2368
+ * then legitimately falls back to the legacy password-derived identity.
2369
+ *
2370
+ * Throws {@link VaultUnavailableError} when the vault itself can't be reached
2371
+ * (network / 5xx / rate-limit) — so a *transient* failure is NOT silently
2372
+ * turned into a legacy fallback (which would surface as "commitment mismatch").
2373
+ */
2374
+ private tryUnlockSeed;
2375
+ /**
2376
+ * Enroll/replace the password factor for `username` — wraps `seed` under the
2377
+ * OPRF-gated key and stores it (needs a session `token`).
2378
+ *
2379
+ * Retries: this is the step that persists the (otherwise in-memory-only)
2380
+ * master seed. If it fails after a fresh registration the account would be
2381
+ * unrecoverable, so we retry a few times before surfacing the error.
2382
+ */
2383
+ private enrollPasswordFactor;
2218
2384
  }
2219
2385
  /** `client.auth` — the auth namespace. Strategies hang off here. */
2220
2386
  declare class AuthNamespace {
@@ -3842,5 +4008,5 @@ declare class KeyringClient implements KeyringTransport {
3842
4008
  fetchMetadata(): Promise<SpaceMetadata | null>;
3843
4009
  }
3844
4010
 
3845
- export { AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES, AgentsNamespace, AuthClient, AuthNamespace, AuthPublicInput, Authenticator, BroadcastChannel, BroadcastChannelEvents, ChannelExistsError, ChannelNotFoundError, ChunkCipher, Client, DEFAULT_BASE_URL, DoubleRatchet, DoubleRatchetCipher, DoubleRatchetManager, EncryptedSession, EventCore, EventCoreEvents, Field, Field as FieldElement, FileStorage, FunctionsNamespace, HashKnowledge, HttpClient, HttpError, KEEPER_MEMBER_ID, KeyStore, KeyringClient, KvNamespace, LocalStorageSessionStore, MemorySessionStore, Message, Message as MessageDefault, MessageNamespace, MuhkooAgent, MuhkooDB, MuhkooFunction, MuhkooSpace, PBKDF2_DEFAULT_ITERATIONS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PersonalSpaceClient, Poseidon, PreimagePoK, ReedSolomonCodec, Space as Room, SerializeMessage, SessionState, ShardClient, SharedSpaceClient, Space, SpaceKeyring, SpaceNamespace, SpacePacketCipher, StorageNamespace, WSTransport, ZkAuth, buildCommitment, compilePrograms, decodeFromHex, decorators, decryptAesGcm, defaultCircuitUrls, defaultSessionStore, deriveAesKeyFromPassphrase, deriveBitsHkdf, deriveIdentity, ejectAgentPrompt, ejectAgentTools, encodeToHex, encryptAesGcm, exportPublicKeyBase64, exportPublicKeyHex, generateAuthProof, getMuhkooAppDescriptor, getSubtle, initBn128Wasm, initRsWasm, initializeCircuits, manifestToStat, poseidonHash, quickVerify, randomBytes, shardHash, signMessage, toField, unwrapWithPassphrase, verify, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase };
3846
- export type { ACL, ACLEntry, AgentConfig, AgentCreateInput, AgentDbToolMode, AgentProvisioned, AgentScopeOpts, AgentSkill, AgentToolsConfig, AgentTrigger, AgentTriggerType, AgentUpdateInput, AgentsNamespaceDeps, AuthClientOptions, AuthKeyPair, AuthSuccess, AuthToken, AuthType, AuthUser, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, ChannelLike, ChunkKeyMaterial, ChunkManifest, CipherFrame, CipherMessage, CipherMessageHeader, CircuitBufferConfig, CircuitUrls, ClientOptions, DehydratedKeypair, DehydratedKeys, DoubleRatchetCipherDeps, ECDHCurve, EncodeResult, EphemeralEvent, EpochKeyProvider, FileManifest, FileNamespaceDeps, FileStat, FileStorageOptions, FunctionCaps, FunctionConfig, FunctionDeployInput, FunctionScopeOpts, FunctionTrigger, FunctionTriggerType, FunctionTriggers, FunctionUpdateInput, FunctionsNamespaceDeps, Groth16Proof, HttpClientOptions, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, KeyringClientDeps, KeyringTransport, KvNamespaceDeps, LoginOptions, MessageBody, MessageDeletedEvent, MessageEvent, MessageHeaders, MessageNamespaceDeps, MessageOptions, MessageSubscription, MuhkooAgentMeta, MuhkooAgentToolsConfig, MuhkooAppDescriptor, MuhkooDBAccess, MuhkooDBMeta, MuhkooFunctionMeta, MuhkooMessageEvent, MuhkooSpaceMeta, OAuthProvider, PacketCipher, PacketHeaders, PacketOptions, Participant, Permission, PermissionCheckRequest, PermissionCheckResult, PersonalSpaceClientOptions, PublicKeyJWK, RatchetState, ReceiveResult, RegisterParams, Role, SpaceDeps as RoomDeps, SpaceFileMetadata as RoomFileMetadata, SealedHeaders, Session, SessionOptions, SessionStore, SetOptions, ShardClientOptions, SharedSpaceClientOptions, SnarkProof, SpaceChannelLike, SpaceDeps, SpaceFileMetadata, SpaceKeyCache, SpaceKeyringDeps, SpaceMessageEvent, SpaceNamespaceDeps, StorageChangeEvent, StoredSession, Subscription, UserIdentity, VerificationKey, WSMessage, WSMessageType, WSTransportOptions, WrappedPayload, WriteFileInput, WriteFileOptions, WriteToShardsInput, ZkAuthDeps, ZkAuthenticateRequest, ZkChallengeResponse, ZkCompiled, ZkIdentity, ZkRegisterRequest, ZkRegisterResponse };
4011
+ export { AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES, AgentsNamespace, AuthClient, AuthNamespace, AuthPublicInput, Authenticator, BroadcastChannel, BroadcastChannelEvents, ChannelExistsError, ChannelNotFoundError, ChunkCipher, Client, DEFAULT_BASE_URL, DoubleRatchet, DoubleRatchetCipher, DoubleRatchetManager, EncryptedSession, EventCore, EventCoreEvents, Field, Field as FieldElement, FileStorage, FunctionsNamespace, HashKnowledge, HttpClient, HttpError, KEEPER_MEMBER_ID, KeyStore, KeyringClient, KvNamespace, LocalStorageSessionStore, MemorySessionStore, Message, Message as MessageDefault, MessageNamespace, MuhkooAgent, MuhkooDB, MuhkooFunction, MuhkooSpace, PBKDF2_DEFAULT_ITERATIONS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PersonalSpaceClient, Poseidon, PreimagePoK, ReedSolomonCodec, Space as Room, SerializeMessage, SessionState, ShardClient, SharedSpaceClient, Space, SpaceKeyring, SpaceNamespace, SpacePacketCipher, StorageNamespace, VaultUnavailableError, WSTransport, ZkAuth, buildCommitment, compilePrograms, decodeFromHex, decorators, decryptAesGcm, defaultCircuitUrls, defaultSessionStore, deriveAesKeyFromPassphrase, deriveBitsHkdf, deriveIdentity, deriveIdentityFromSeed, deriveMasterSeedFromPassword, ejectAgentPrompt, ejectAgentTools, encodeToHex, encryptAesGcm, exportPublicKeyBase64, exportPublicKeyHex, generateAuthProof, getMuhkooAppDescriptor, getSubtle, initBn128Wasm, initRsWasm, initializeCircuits, manifestToStat, poseidonHash, quickVerify, randomBytes, shardHash, signMessage, toField, unwrapWithPassphrase, verify, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase };
4012
+ export type { ACL, ACLEntry, AgentConfig, AgentCreateInput, AgentDbToolMode, AgentProvisioned, AgentScopeOpts, AgentSkill, AgentToolsConfig, AgentTrigger, AgentTriggerType, AgentUpdateInput, AgentsNamespaceDeps, AuthClientOptions, AuthKeyPair, AuthSuccess, AuthToken, AuthType, AuthUser, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, ChannelLike, ChunkKeyMaterial, ChunkManifest, CipherFrame, CipherMessage, CipherMessageHeader, CircuitBufferConfig, CircuitUrls, ClientOptions, DehydratedKeypair, DehydratedKeys, DoubleRatchetCipherDeps, ECDHCurve, EncodeResult, EphemeralEvent, EpochKeyProvider, FileManifest, FileNamespaceDeps, FileStat, FileStorageOptions, FunctionCaps, FunctionConfig, FunctionDeployInput, FunctionScopeOpts, FunctionTrigger, FunctionTriggerType, FunctionTriggers, FunctionUpdateInput, FunctionsNamespaceDeps, Groth16Proof, HttpClientOptions, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, KeyringClientDeps, KeyringTransport, KvNamespaceDeps, LoginOptions, MessageBody, MessageDeletedEvent, MessageEvent, MessageHeaders, MessageNamespaceDeps, MessageOptions, MessageSubscription, MuhkooAgentMeta, MuhkooAgentToolsConfig, MuhkooAppDescriptor, MuhkooDBAccess, MuhkooDBMeta, MuhkooFunctionMeta, MuhkooMessageEvent, MuhkooSpaceMeta, OAuthProvider, PacketCipher, PacketHeaders, PacketOptions, Participant, Permission, PermissionCheckRequest, PermissionCheckResult, PersonalSpaceClientOptions, PublicKeyJWK, RatchetState, ReceiveResult, RegisterParams, Role, SpaceDeps as RoomDeps, SpaceFileMetadata as RoomFileMetadata, SealedHeaders, Session, SessionOptions, SessionStore, SetOptions, ShardClientOptions, SharedSpaceClientOptions, SnarkProof, SpaceChannelLike, SpaceDeps, SpaceFileMetadata, SpaceKeyCache, SpaceKeyringDeps, SpaceMessageEvent, SpaceNamespaceDeps, StorageChangeEvent, StoredSession, Subscription, UserIdentity, VaultFactor, VerificationKey, WSMessage, WSMessageType, WSTransportOptions, WrappedPayload, WriteFileInput, WriteFileOptions, WriteToShardsInput, ZkAuthDeps, ZkAuthenticateRequest, ZkChallengeResponse, ZkCompiled, ZkIdentity, ZkRegisterRequest, ZkRegisterResponse };