@muhkoo/connect 0.10.13-alpha.0 → 0.11.0-alpha.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.
- package/dist/browser/index.js +1283 -83
- package/dist/browser/index.js.map +1 -1
- package/dist/connect.d.ts +434 -11
- package/dist/server/index.js +1283 -83
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/connect.d.ts
CHANGED
|
@@ -1897,7 +1897,7 @@ interface AuthSuccess {
|
|
|
1897
1897
|
/** A vault factor record (M1.0 + M2 gated types). Wrap/iv are base64 AES-GCM; absent for phrase. */
|
|
1898
1898
|
interface VaultFactor {
|
|
1899
1899
|
id: string;
|
|
1900
|
-
type: "password" | "passkey" | "phrase-marker" | "email" | "google";
|
|
1900
|
+
type: "password" | "passkey" | "phrase-marker" | "email" | "google" | "device";
|
|
1901
1901
|
wrap?: string;
|
|
1902
1902
|
iv?: string;
|
|
1903
1903
|
params?: Record<string, unknown>;
|
|
@@ -2009,7 +2009,9 @@ declare class AuthClient {
|
|
|
2009
2009
|
/** Passkeys are per-origin: naming the caller's host returns THAT origin's
|
|
2010
2010
|
* passkey instead of whichever was enrolled first (which WebAuthn would
|
|
2011
2011
|
* refuse). Ignored for other factor types. */
|
|
2012
|
-
rpId?: string
|
|
2012
|
+
rpId?: string,
|
|
2013
|
+
/** Device factors are selected by id — a user may have many machines. */
|
|
2014
|
+
factorId?: string): Promise<{
|
|
2013
2015
|
factor: VaultFactor | null;
|
|
2014
2016
|
}>;
|
|
2015
2017
|
/**
|
|
@@ -2833,12 +2835,22 @@ declare class HostedAuth {
|
|
|
2833
2835
|
/**
|
|
2834
2836
|
* The account's paired devices. Session-authed.
|
|
2835
2837
|
*
|
|
2836
|
-
* UI copy note (spec §10.6): removing a device
|
|
2837
|
-
*
|
|
2838
|
-
*
|
|
2838
|
+
* UI copy note (spec §10.6): removing a device forces a full re-approval next
|
|
2839
|
+
* time, but be careful what you promise. It does NOT sign the device out —
|
|
2840
|
+
* the server returns `session_revoked: false`, and that session runs until it
|
|
2841
|
+
* expires — and it cannot take back the master seed the device already holds.
|
|
2842
|
+
* Users assume "remove" means "locked out immediately"; it does not.
|
|
2839
2843
|
*/
|
|
2840
2844
|
listPairedDevices(): Promise<PairedDevice[]>;
|
|
2841
|
-
/**
|
|
2845
|
+
/**
|
|
2846
|
+
* Un-pair a device. Session-authed.
|
|
2847
|
+
*
|
|
2848
|
+
* It stops being a "known" device, so pairing it again needs full approval
|
|
2849
|
+
* with a fresh factor. It does NOT end that device's current session — the
|
|
2850
|
+
* server reports `session_revoked: false` — and it cannot take back the
|
|
2851
|
+
* master seed the device already holds. Do not write UI copy promising an
|
|
2852
|
+
* immediate sign-out; users will assume it and be wrong.
|
|
2853
|
+
*/
|
|
2842
2854
|
revokePairedDevice(id: string): Promise<void>;
|
|
2843
2855
|
/**
|
|
2844
2856
|
* The whole tail of an approved pairing: unseal → derive → **verify** →
|
|
@@ -2956,10 +2968,6 @@ interface ZkAuthDeps {
|
|
|
2956
2968
|
circuits: CircuitUrls;
|
|
2957
2969
|
session: SessionState;
|
|
2958
2970
|
}
|
|
2959
|
-
/**
|
|
2960
|
-
* ZK identity auth. One instance per {@link Client}; reads/writes the shared
|
|
2961
|
-
* {@link SessionState}.
|
|
2962
|
-
*/
|
|
2963
2971
|
declare class ZkAuth {
|
|
2964
2972
|
private readonly deps;
|
|
2965
2973
|
constructor(deps: ZkAuthDeps);
|
|
@@ -3174,6 +3182,63 @@ declare class ZkAuth {
|
|
|
3174
3182
|
* passwordless (passkey) login, both of which recover the same seed.
|
|
3175
3183
|
*/
|
|
3176
3184
|
get seedBase64(): string | null;
|
|
3185
|
+
/**
|
|
3186
|
+
* Pair this machine, so it can unlock the account later without a password.
|
|
3187
|
+
*
|
|
3188
|
+
* Generates a random 32-byte key, wraps the master seed under it, and stores
|
|
3189
|
+
* only the CIPHERTEXT in the vault as a `device` factor. The key is returned
|
|
3190
|
+
* for the caller to persist locally and is never sent anywhere.
|
|
3191
|
+
*
|
|
3192
|
+
* The split is the point: the seed itself never lands on disk, and the
|
|
3193
|
+
* server holds a blob it cannot open. Revoking the factor
|
|
3194
|
+
* ({@link revokeDevice}) makes the local key inert immediately — which a
|
|
3195
|
+
* stored master seed can never be, because nothing can reach out and
|
|
3196
|
+
* un-store it.
|
|
3197
|
+
*
|
|
3198
|
+
* Returns the factor id and the key, both base64. Losing the key just means
|
|
3199
|
+
* re-pairing; leaking it is equivalent to leaking the seed for as long as
|
|
3200
|
+
* the factor exists, so store it with the tightest permissions available.
|
|
3201
|
+
*/
|
|
3202
|
+
enrollDevice(label: string): Promise<{
|
|
3203
|
+
factorId: string;
|
|
3204
|
+
deviceKey: string;
|
|
3205
|
+
}>;
|
|
3206
|
+
/**
|
|
3207
|
+
* Unlock using a key stored by {@link enrollDevice}.
|
|
3208
|
+
*
|
|
3209
|
+
* Fetches the wrapped seed and opens it locally. Establishes the encryption
|
|
3210
|
+
* identity only — pair it with a session for calls that need one.
|
|
3211
|
+
*
|
|
3212
|
+
* Throws distinguishably: a REVOKED factor is gone from the vault and says
|
|
3213
|
+
* so, where a wrong key fails to decrypt. A machine that has had its access
|
|
3214
|
+
* withdrawn should be able to tell you that, not just "decryption failed".
|
|
3215
|
+
*/
|
|
3216
|
+
unlockWithDevice(username: string, factorId: string, deviceKey: string): Promise<void>;
|
|
3217
|
+
/** Paired machines, newest first. Metadata only — never the ciphertext. */
|
|
3218
|
+
listDevices(): Promise<Array<{
|
|
3219
|
+
id: string;
|
|
3220
|
+
label?: string;
|
|
3221
|
+
createdAt?: number;
|
|
3222
|
+
}>>;
|
|
3223
|
+
/** Withdraw a machine's access. Its stored key stops working immediately. */
|
|
3224
|
+
revokeDevice(factorId: string): Promise<boolean>;
|
|
3225
|
+
/**
|
|
3226
|
+
* Restore an unlocked identity from a seed you already hold.
|
|
3227
|
+
*
|
|
3228
|
+
* The inverse of {@link seedBase64}, for hosts that persist the seed
|
|
3229
|
+
* themselves rather than re-deriving it from a password: a CLI holding it in
|
|
3230
|
+
* a 0600 file, a server-side tool, a test. Without this the seed is a
|
|
3231
|
+
* one-way export and anything outside a browser has to run a full ZK login —
|
|
3232
|
+
* circuits download and proof — on every single invocation.
|
|
3233
|
+
*
|
|
3234
|
+
* Establishes the ENCRYPTION identity only. It does not authenticate: pair
|
|
3235
|
+
* it with a session token (`sessionStore`) for calls that need one.
|
|
3236
|
+
*
|
|
3237
|
+
* Treat a persisted seed as the master credential it is. It is not scoped
|
|
3238
|
+
* and cannot be revoked server-side the way a session token can — rotating
|
|
3239
|
+
* it means moving the identity.
|
|
3240
|
+
*/
|
|
3241
|
+
unlockWithSeed(seedBase64: string): void;
|
|
3177
3242
|
/** Poseidon commitment for an identity — the value the server stores. */
|
|
3178
3243
|
private commitmentFor;
|
|
3179
3244
|
/**
|
|
@@ -3756,6 +3821,8 @@ interface StorageChangeEvent<T = unknown> {
|
|
|
3756
3821
|
}
|
|
3757
3822
|
declare class KvNamespace {
|
|
3758
3823
|
private readonly deps;
|
|
3824
|
+
/** One personal-space socket, shared by every subscriber. */
|
|
3825
|
+
private feed;
|
|
3759
3826
|
private cipher;
|
|
3760
3827
|
private cipherIdentity;
|
|
3761
3828
|
constructor(deps: KvNamespaceDeps);
|
|
@@ -3779,6 +3846,20 @@ declare class KvNamespace {
|
|
|
3779
3846
|
* Requires a `WebSocket` global (browsers; Node 22+ or a `ws` shim).
|
|
3780
3847
|
*/
|
|
3781
3848
|
on<T = unknown>(event: "change", handler: (e: StorageChangeEvent<T>) => void): () => void;
|
|
3849
|
+
/**
|
|
3850
|
+
* Subscribe to the personal space's raw change feed.
|
|
3851
|
+
*
|
|
3852
|
+
* Every key this user owns crosses this socket, not only `client.kv`
|
|
3853
|
+
* collections — the VFS keeps its directory records here too. Consumers get
|
|
3854
|
+
* the frame untouched: no decryption, no offline-cache merge, because the
|
|
3855
|
+
* value's meaning depends on which subsystem wrote it.
|
|
3856
|
+
*
|
|
3857
|
+
* The transport is SHARED and reference-counted. `WSTransport` namespaces
|
|
3858
|
+
* its events by `id`, so two transports with the same id would cross wires
|
|
3859
|
+
* on the shared event bus — and a second socket to the same Durable Object
|
|
3860
|
+
* would be pure waste besides.
|
|
3861
|
+
*/
|
|
3862
|
+
onRaw(handler: (frame: unknown) => void): () => void;
|
|
3782
3863
|
private dispatchChange;
|
|
3783
3864
|
/** Decode a stored value: decrypt envelopes, pass plaintext through. */
|
|
3784
3865
|
private decode;
|
|
@@ -4905,9 +4986,20 @@ declare class SpaceNamespace {
|
|
|
4905
4986
|
* Create a new space: generate its keypair (public key = id), register
|
|
4906
4987
|
* metadata, mint the initial group key, and connect. Returns the open Space.
|
|
4907
4988
|
*/
|
|
4989
|
+
/**
|
|
4990
|
+
* Create a space.
|
|
4991
|
+
*
|
|
4992
|
+
* `messaging: false` registers the space and stops there — no group-key
|
|
4993
|
+
* bootstrap and no WebSocket. Use it for a space that only ever holds
|
|
4994
|
+
* FILES: each chunk carries its own key inside its manifest, so the group
|
|
4995
|
+
* keyring buys nothing, and opening a socket makes the write path depend on
|
|
4996
|
+
* a live connection. That dependency is wrong for a CLI, and it is what made
|
|
4997
|
+
* the first VFS write hang forever instead of failing.
|
|
4998
|
+
*/
|
|
4908
4999
|
createSpace(opts?: {
|
|
4909
5000
|
historyPolicy?: HistoryPolicy;
|
|
4910
5001
|
private?: boolean;
|
|
5002
|
+
messaging?: boolean;
|
|
4911
5003
|
}): Promise<Space>;
|
|
4912
5004
|
/** Join an existing space by id (its public key). Resolves once a key arrives. */
|
|
4913
5005
|
joinSpace(spaceId: string, opts?: {
|
|
@@ -5369,6 +5461,318 @@ declare class AccessTokensNamespace {
|
|
|
5369
5461
|
private path;
|
|
5370
5462
|
}
|
|
5371
5463
|
|
|
5464
|
+
/**
|
|
5465
|
+
* Wire types for the VFS metadata layer.
|
|
5466
|
+
*
|
|
5467
|
+
* ## What is stored where
|
|
5468
|
+
*
|
|
5469
|
+
* The filesystem is a graph of **directory records**, one per directory, each
|
|
5470
|
+
* held under a personal-space KV key and encrypted client-side. A record lists
|
|
5471
|
+
* only its immediate children — so listing a directory is one fetch, and you
|
|
5472
|
+
* only ever pay for the subtrees you actually open.
|
|
5473
|
+
*
|
|
5474
|
+
* File CONTENT is not here. Bytes are written with `client.storage.writeFile`
|
|
5475
|
+
* exactly as any other file — into a real Space, with a real gated manifest —
|
|
5476
|
+
* and the entry keeps the returned `FileManifest` as its handle.
|
|
5477
|
+
* `client.storage.readByManifest(manifest)` then reconstructs the bytes from
|
|
5478
|
+
* the content-addressed shard store with no space membership or directory
|
|
5479
|
+
* lookup needed, which is what makes a file shareable by handing over the
|
|
5480
|
+
* handle alone.
|
|
5481
|
+
*
|
|
5482
|
+
* This supersedes the flat personal mirror `writeFile` already maintains
|
|
5483
|
+
* (`{spaceId, manifest}` keyed by manifest id): the same metadata, in the same
|
|
5484
|
+
* personal space, arranged as a tree you can actually navigate.
|
|
5485
|
+
*
|
|
5486
|
+
* ## Why directories have stable random ids, not content hashes
|
|
5487
|
+
*
|
|
5488
|
+
* A git-style tree keys each directory by the hash of its contents, so writing
|
|
5489
|
+
* one file rewrites every ancestor up to the root. Here a directory's id is
|
|
5490
|
+
* random and permanent, so a file write touches exactly ONE record — its
|
|
5491
|
+
* parent — and renaming or moving a directory edits only the parent entry
|
|
5492
|
+
* while the whole subtree underneath stays byte-identical and untouched.
|
|
5493
|
+
*
|
|
5494
|
+
* ## Why a directory's key lives in its parent
|
|
5495
|
+
*
|
|
5496
|
+
* Only the root key is derived from the master seed. Every other directory has
|
|
5497
|
+
* a random key stored in its parent's entry, which chains capabilities
|
|
5498
|
+
* downward: handing someone `{id, key}` for `/apps/my-app` lets them walk that
|
|
5499
|
+
* subtree and nothing else, because no key can be derived upward. That is the
|
|
5500
|
+
* seam group-sharing hangs off later without re-encrypting the filesystem.
|
|
5501
|
+
*/
|
|
5502
|
+
|
|
5503
|
+
/** What `stat` and `list` hand back — a path-addressed view of an entry. */
|
|
5504
|
+
interface VfsStat {
|
|
5505
|
+
path: string;
|
|
5506
|
+
name: string;
|
|
5507
|
+
kind: "file" | "dir";
|
|
5508
|
+
size: number;
|
|
5509
|
+
mtime: number;
|
|
5510
|
+
versions: number;
|
|
5511
|
+
}
|
|
5512
|
+
/** The personal-space blob store the VFS persists through. */
|
|
5513
|
+
interface VfsStore {
|
|
5514
|
+
get(key: string): Promise<unknown | null>;
|
|
5515
|
+
put(key: string, value: unknown): Promise<void>;
|
|
5516
|
+
delete(key: string): Promise<void>;
|
|
5517
|
+
/** Every key in the store — the personal space is shared, so this is NOT VFS-only. */
|
|
5518
|
+
list(): Promise<string[]>;
|
|
5519
|
+
}
|
|
5520
|
+
|
|
5521
|
+
/**
|
|
5522
|
+
* `client.vfs` — a real filesystem over Muhkoo primitives.
|
|
5523
|
+
*
|
|
5524
|
+
* Metadata is a graph of encrypted directory records in the user's personal
|
|
5525
|
+
* space; file content is chunked, encrypted and stored in the global
|
|
5526
|
+
* content-addressed shard store, referenced by manifest. See `types.ts` for
|
|
5527
|
+
* why directories carry stable random ids and why each key lives in its parent.
|
|
5528
|
+
*
|
|
5529
|
+
* ## Consistency
|
|
5530
|
+
*
|
|
5531
|
+
* Every mutation is a read-modify-write of exactly ONE directory record, so a
|
|
5532
|
+
* write cannot leave the tree half-updated: either the parent names the new
|
|
5533
|
+
* child or it does not. Two tabs writing different directories never conflict;
|
|
5534
|
+
* two tabs writing the SAME directory resolve last-writer-wins at the personal
|
|
5535
|
+
* space, which carries an HLC per key. Orphaned records (a directory whose
|
|
5536
|
+
* parent entry lost the race) are unreachable rather than corrupting — they
|
|
5537
|
+
* cost storage until a future sweep, which is the trade this shape makes in
|
|
5538
|
+
* exchange for single-record writes.
|
|
5539
|
+
*/
|
|
5540
|
+
|
|
5541
|
+
/**
|
|
5542
|
+
* The slice of content storage the VFS needs.
|
|
5543
|
+
*
|
|
5544
|
+
* Narrow on purpose: the VFS knows how to name and arrange things, not how to
|
|
5545
|
+
* shard them. The adapter in `Client` resolves the content space and calls
|
|
5546
|
+
* `client.storage.writeFile` unchanged — the file still lands in a real Space
|
|
5547
|
+
* with a real gated manifest, and the VFS just keeps the handle somewhere
|
|
5548
|
+
* better than a flat mirror.
|
|
5549
|
+
*/
|
|
5550
|
+
interface VfsContentStore {
|
|
5551
|
+
write(data: Uint8Array | Blob, meta: {
|
|
5552
|
+
name: string;
|
|
5553
|
+
type: string;
|
|
5554
|
+
}): Promise<{
|
|
5555
|
+
manifest: FileManifest;
|
|
5556
|
+
size: number;
|
|
5557
|
+
}>;
|
|
5558
|
+
read(manifest: FileManifest): Promise<Uint8Array>;
|
|
5559
|
+
/**
|
|
5560
|
+
* Drop a reference to a manifest's shards.
|
|
5561
|
+
*
|
|
5562
|
+
* Shards are content-addressed and reference-counted, so deleting a file is
|
|
5563
|
+
* not enough to reclaim the bytes — without this, every version ever
|
|
5564
|
+
* written stays on disk and billed forever. Best-effort: a failure here
|
|
5565
|
+
* leaks storage but must not block the delete.
|
|
5566
|
+
*/
|
|
5567
|
+
release(manifest: FileManifest): Promise<void>;
|
|
5568
|
+
/**
|
|
5569
|
+
* Take an ADDITIONAL reference to shards that already exist.
|
|
5570
|
+
*
|
|
5571
|
+
* Needed when a manifest gains a second owner without new bytes being
|
|
5572
|
+
* written — copying a file. Without it the copy holds a handle to shards
|
|
5573
|
+
* with a refcount of one, and deleting the original frees the bytes out
|
|
5574
|
+
* from under it.
|
|
5575
|
+
*/
|
|
5576
|
+
retain(manifest: FileManifest): Promise<void>;
|
|
5577
|
+
}
|
|
5578
|
+
interface VfsNamespaceDeps {
|
|
5579
|
+
store: VfsStore;
|
|
5580
|
+
/**
|
|
5581
|
+
* Subscribe to the personal space's raw change feed, if the runtime has one.
|
|
5582
|
+
* Optional so the VFS works headlessly (a CLI, a test) with no socket.
|
|
5583
|
+
*/
|
|
5584
|
+
subscribe?: (handler: (frame: unknown) => void) => () => void;
|
|
5585
|
+
content: VfsContentStore;
|
|
5586
|
+
/** The in-memory master seed, or null when locked. Read per call — it can change. */
|
|
5587
|
+
seed: () => Uint8Array | null;
|
|
5588
|
+
/** Versions retained per file. */
|
|
5589
|
+
historyLimit?: number;
|
|
5590
|
+
}
|
|
5591
|
+
declare class VfsNamespace {
|
|
5592
|
+
private readonly deps;
|
|
5593
|
+
private rootKey;
|
|
5594
|
+
/**
|
|
5595
|
+
* Decrypted directory records, by id.
|
|
5596
|
+
*
|
|
5597
|
+
* The file tree re-lists constantly while typing, and every miss is a
|
|
5598
|
+
* network round trip plus a decrypt. Invalidated precisely on write rather
|
|
5599
|
+
* than by TTL — a stale directory listing shows files that are not there.
|
|
5600
|
+
*/
|
|
5601
|
+
private cache;
|
|
5602
|
+
private readonly historyLimit;
|
|
5603
|
+
constructor(deps: VfsNamespaceDeps);
|
|
5604
|
+
/**
|
|
5605
|
+
* The working directory relative paths resolve against.
|
|
5606
|
+
*
|
|
5607
|
+
* Kept here rather than left to each caller so that a CLI, a script and the
|
|
5608
|
+
* SDK all agree on what "here" means — the alternative is every consumer
|
|
5609
|
+
* re-implementing `cd`, and disagreeing about `..`.
|
|
5610
|
+
*/
|
|
5611
|
+
private _cwd;
|
|
5612
|
+
/** The current working directory. Always absolute. */
|
|
5613
|
+
get cwd(): string;
|
|
5614
|
+
/**
|
|
5615
|
+
* Change the working directory.
|
|
5616
|
+
*
|
|
5617
|
+
* Verifies the target is a real directory, so a typo fails here — where the
|
|
5618
|
+
* message can name the path — rather than turning every later relative path
|
|
5619
|
+
* into a confusing "does not exist".
|
|
5620
|
+
*/
|
|
5621
|
+
cd(path: string): Promise<string>;
|
|
5622
|
+
/** Resolve a path against the working directory. Absolute paths pass through. */
|
|
5623
|
+
resolve(path: string): string;
|
|
5624
|
+
/** True when the master seed is held, so the root key can be derived. */
|
|
5625
|
+
get unlocked(): boolean;
|
|
5626
|
+
/**
|
|
5627
|
+
* Drop every cached record.
|
|
5628
|
+
*
|
|
5629
|
+
* Call after signing in as someone else — the cache is keyed by directory
|
|
5630
|
+
* id with no notion of whose filesystem it came from, and serving one
|
|
5631
|
+
* identity's directories to another would be the worst possible bug here.
|
|
5632
|
+
*/
|
|
5633
|
+
clearCache(): void;
|
|
5634
|
+
/**
|
|
5635
|
+
* Call `handler` when this filesystem changes somewhere else — another tab,
|
|
5636
|
+
* another machine, the CLI.
|
|
5637
|
+
*
|
|
5638
|
+
* Deliberately a NOTIFICATION, not a diff: the frame names a record id, and
|
|
5639
|
+
* a record id is not a path (paths are resolved by walking, and the walk is
|
|
5640
|
+
* what the change may have invalidated). So the cache is dropped and the
|
|
5641
|
+
* caller re-reads whatever it is actually showing. Trying to translate a
|
|
5642
|
+
* record id back into a path would mean maintaining a reverse index that
|
|
5643
|
+
* could itself go stale.
|
|
5644
|
+
*
|
|
5645
|
+
* Returns an unsubscribe function. A runtime with no socket (a CLI) gets a
|
|
5646
|
+
* no-op rather than an error — watching is an optimisation, never required
|
|
5647
|
+
* for correctness.
|
|
5648
|
+
*/
|
|
5649
|
+
watch(handler: () => void): () => void;
|
|
5650
|
+
exists(path: string): Promise<boolean>;
|
|
5651
|
+
stat(path: string): Promise<VfsStat>;
|
|
5652
|
+
/** Immediate children of a directory. One record fetch. */
|
|
5653
|
+
list(path?: string): Promise<VfsStat[]>;
|
|
5654
|
+
/**
|
|
5655
|
+
* Every file path under a prefix, depth-first.
|
|
5656
|
+
*
|
|
5657
|
+
* Deliberately separate from `list`: this walks the whole subtree, which is
|
|
5658
|
+
* one fetch per directory. Fine for a project, wrong as a default.
|
|
5659
|
+
*/
|
|
5660
|
+
walk(path?: string): Promise<string[]>;
|
|
5661
|
+
readFile(path: string): Promise<Uint8Array>;
|
|
5662
|
+
readText(path: string): Promise<string>;
|
|
5663
|
+
/**
|
|
5664
|
+
* Create a directory. `recursive` creates missing parents and tolerates an
|
|
5665
|
+
* existing target, matching `mkdir -p`.
|
|
5666
|
+
*/
|
|
5667
|
+
mkdir(path: string, opts?: {
|
|
5668
|
+
recursive?: boolean;
|
|
5669
|
+
}): Promise<void>;
|
|
5670
|
+
/**
|
|
5671
|
+
* Write a file, creating parent directories as needed.
|
|
5672
|
+
*
|
|
5673
|
+
* The previous version is pushed onto the file's history record before the
|
|
5674
|
+
* directory entry is replaced, so an interrupted write can lose the new
|
|
5675
|
+
* version but never the old one.
|
|
5676
|
+
*/
|
|
5677
|
+
writeFile(path: string, data: Uint8Array | string | Blob, opts?: {
|
|
5678
|
+
type?: string;
|
|
5679
|
+
}): Promise<VfsStat>;
|
|
5680
|
+
/** Delete a file, or a directory when `recursive`. */
|
|
5681
|
+
delete(path: string, opts?: {
|
|
5682
|
+
recursive?: boolean;
|
|
5683
|
+
}): Promise<void>;
|
|
5684
|
+
/**
|
|
5685
|
+
* Move or rename. Works across directories, which is the same operation:
|
|
5686
|
+
* detach the entry from one parent and attach it to another.
|
|
5687
|
+
*
|
|
5688
|
+
* A directory move is O(1) regardless of how much is inside it — the
|
|
5689
|
+
* subtree records are not touched at all, because nothing in them records
|
|
5690
|
+
* its own path.
|
|
5691
|
+
*/
|
|
5692
|
+
rename(from: string, to: string): Promise<void>;
|
|
5693
|
+
/**
|
|
5694
|
+
* Copy a file or a directory tree.
|
|
5695
|
+
*
|
|
5696
|
+
* Copying a FILE moves no bytes: content is immutable and content-addressed,
|
|
5697
|
+
* so the new entry simply points at the same manifest. A 200 MB asset
|
|
5698
|
+
* duplicates in one small metadata write, and the shard store already holds
|
|
5699
|
+
* exactly one copy of it.
|
|
5700
|
+
*
|
|
5701
|
+
* The copy gets a NEW file id, so it does not inherit or share history —
|
|
5702
|
+
* two paths sharing an id would mean saving one silently pushed a version
|
|
5703
|
+
* onto the other.
|
|
5704
|
+
*/
|
|
5705
|
+
copy(from: string, to: string): Promise<VfsStat>;
|
|
5706
|
+
/**
|
|
5707
|
+
* Paths matching a glob, relative to the whole filesystem.
|
|
5708
|
+
*
|
|
5709
|
+
* Matching happens on the client over a walk of the tree, so the cost is one
|
|
5710
|
+
* record fetch per directory — cheap for a project, and worth knowing before
|
|
5711
|
+
* pointing it at the root of a large filesystem. Use `walk` when the prefix
|
|
5712
|
+
* already narrows it.
|
|
5713
|
+
*/
|
|
5714
|
+
glob(pattern: string, opts?: {
|
|
5715
|
+
from?: string;
|
|
5716
|
+
}): Promise<string[]>;
|
|
5717
|
+
/**
|
|
5718
|
+
* Delete metadata records no longer reachable from the root.
|
|
5719
|
+
*
|
|
5720
|
+
* These accumulate because every write touches exactly one record: if two
|
|
5721
|
+
* tabs edit the same directory, last-writer-wins at the personal space can
|
|
5722
|
+
* leave a child whose parent entry lost the race. Unreachable is harmless —
|
|
5723
|
+
* it is invisible and undecryptable-by-nobody — but it costs storage, so
|
|
5724
|
+
* this reclaims it.
|
|
5725
|
+
*
|
|
5726
|
+
* Deliberately explicit, never automatic: a sweep racing another tab's
|
|
5727
|
+
* in-flight write could delete a record that is about to be referenced.
|
|
5728
|
+
* Run it when the filesystem is idle.
|
|
5729
|
+
*/
|
|
5730
|
+
sweep(opts?: {
|
|
5731
|
+
force?: boolean;
|
|
5732
|
+
}): Promise<{
|
|
5733
|
+
removed: string[];
|
|
5734
|
+
}>;
|
|
5735
|
+
/** Prior versions of a file, newest first. One record fetch. */
|
|
5736
|
+
history(path: string): Promise<Array<{
|
|
5737
|
+
size: number;
|
|
5738
|
+
mtime: number;
|
|
5739
|
+
}>>;
|
|
5740
|
+
/**
|
|
5741
|
+
* Restore a prior version, where 0 is the most recent one.
|
|
5742
|
+
*
|
|
5743
|
+
* The current version is pushed onto history first, so restoring is itself
|
|
5744
|
+
* undoable rather than a one-way door.
|
|
5745
|
+
*/
|
|
5746
|
+
restore(path: string, index?: number): Promise<VfsStat>;
|
|
5747
|
+
private expectFile;
|
|
5748
|
+
/** Resolve a path to its entry, or null. Root has no entry of its own. */
|
|
5749
|
+
private find;
|
|
5750
|
+
private root;
|
|
5751
|
+
/** Open a directory by path, creating nothing. Throws if it is missing. */
|
|
5752
|
+
private openDir;
|
|
5753
|
+
private openDirOrNull;
|
|
5754
|
+
private openDirById;
|
|
5755
|
+
/** Apply an edit to a directory record and persist it. */
|
|
5756
|
+
private mutate;
|
|
5757
|
+
private createDir;
|
|
5758
|
+
/** Recursively remove a subtree's records. Best-effort: unreachable ≠ fatal. */
|
|
5759
|
+
private purge;
|
|
5760
|
+
/**
|
|
5761
|
+
* Deep-copy an entry. Files reuse their manifest (no bytes move); each
|
|
5762
|
+
* directory gets a fresh id and key, so the copy is independent of the
|
|
5763
|
+
* original — writing into one must never appear in the other.
|
|
5764
|
+
*/
|
|
5765
|
+
private cloneEntry;
|
|
5766
|
+
/**
|
|
5767
|
+
* Let go of a file's bytes: the current manifest and every retained
|
|
5768
|
+
* version, then the history record itself.
|
|
5769
|
+
*/
|
|
5770
|
+
private releaseFile;
|
|
5771
|
+
private readHistory;
|
|
5772
|
+
/** Push `entry` onto its history record. Returns the new version count. */
|
|
5773
|
+
private pushHistory;
|
|
5774
|
+
}
|
|
5775
|
+
|
|
5372
5776
|
/** The hosted Muhkoo Accelerator — the default {@link ClientOptions.baseUrl}. */
|
|
5373
5777
|
declare const DEFAULT_BASE_URL = "https://api.muhkoo.dev";
|
|
5374
5778
|
/** The hosted auth SPA — the default {@link ClientOptions.authBaseUrl}. */
|
|
@@ -5466,6 +5870,8 @@ declare class Client {
|
|
|
5466
5870
|
readonly db: DbNamespace;
|
|
5467
5871
|
/** File storage — `client.storage.writeFile(...)`, etc. */
|
|
5468
5872
|
readonly storage: StorageNamespace;
|
|
5873
|
+
/** Filesystem over the personal space: directories, versions, real paths. */
|
|
5874
|
+
readonly vfs: VfsNamespace;
|
|
5469
5875
|
/** Realtime messaging — `client.message.subscribe(...)`, etc. */
|
|
5470
5876
|
readonly message: MessageNamespace;
|
|
5471
5877
|
/** Fan-out group spaces — `client.space.createSpace(...)`, etc. */
|
|
@@ -5705,6 +6111,23 @@ declare function defaultRpId(): string;
|
|
|
5705
6111
|
* sign-in (and offer to enroll a passkey for this origin) instead.
|
|
5706
6112
|
*/
|
|
5707
6113
|
declare function rpIdUsableForOrigin(rpId: string | undefined | null, host?: string): boolean;
|
|
6114
|
+
/**
|
|
6115
|
+
* Would {@link AuthNamespace.loginWithPasskey} accept a factor recorded with
|
|
6116
|
+
* this `rpId`, from `host`?
|
|
6117
|
+
*
|
|
6118
|
+
* This is deliberately NOT the same as {@link rpIdUsableForOrigin}. That answers
|
|
6119
|
+
* a raw WebAuthn question and is `false` for a missing rpId. But a factor with
|
|
6120
|
+
* NO recorded rpId predates per-origin enrolment, and `loginWithPasskey`
|
|
6121
|
+
* resolves it as `params.rpId ?? host` — so it IS usable, from anywhere.
|
|
6122
|
+
*
|
|
6123
|
+
* Callers deciding "should I even try a passkey here?" must use this one.
|
|
6124
|
+
* Reaching for `rpIdUsableForOrigin` instead silently excludes every legacy
|
|
6125
|
+
* passkey holder, which has locked real users out of production twice.
|
|
6126
|
+
*
|
|
6127
|
+
* The `?? host` fallback applies to nullish only, matching `loginWithPasskey`:
|
|
6128
|
+
* an empty-string rpId stays unusable rather than resolving to the host.
|
|
6129
|
+
*/
|
|
6130
|
+
declare function passkeyUsableFromOrigin(rpId: string | undefined | null, host?: string): boolean;
|
|
5708
6131
|
/** Thrown when the account's passkey belongs to a different origin. Callers
|
|
5709
6132
|
* should treat this as "no passkey here" and fall back to another factor. */
|
|
5710
6133
|
declare class PasskeyOriginError extends Error {
|
|
@@ -6632,5 +7055,5 @@ declare class KeyringClient implements KeyringTransport {
|
|
|
6632
7055
|
fetchMetadata(): Promise<SpaceMetadata | null>;
|
|
6633
7056
|
}
|
|
6634
7057
|
|
|
6635
|
-
export { ACCESS_TOKEN_SCOPES, AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES, AccessTokensNamespace, AgentsNamespace, AuthClient, AuthNamespace, AuthPublicInput, Authenticator, BlockEngine, BroadcastChannel, BroadcastChannelEvents, ChannelExistsError, ChannelNotFoundError, ChunkCipher, Client, ConnectivityManager, DEFAULT_AUTH_BASE_URL, DEFAULT_BASE_URL, DEFAULT_FN_HOST_SUFFIX, DEVICE_IDENTITY_STORAGE_KEY, DEVICE_KEY_DB_NAME, DbCache, DevicePairingError, DeviceStoreUnavailableError, DoubleRatchet, DoubleRatchetCipher, DoubleRatchetManager, EncryptedSession, EventCore, EventCoreEvents, Field, Field as FieldElement, FileStorage, FunctionsNamespace, HLC, HashKnowledge, HostedAuth, HttpClient, HttpError, IndexedDbStore, KEEPER_MEMBER_ID, KeyStore, KeyringClient, KvCache, KvNamespace, LocalEngineHost, LocalStorageSessionStore, MemorySessionStore, Message, Message as MessageDefault, MessageNamespace, MuhkooAgent, MuhkooDB, MuhkooFunction, MuhkooSpace, NoopStore, OfflineLockedError, OfflineManager, OutboundQueue, P2P_SUBJECT, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, PBKDF2_DEFAULT_ITERATIONS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PasskeyOriginError, PeerExchange, PeerNetwork, PersonalSpaceClient, Poseidon, PreimagePoK, ReauthRequiredError, ReedSolomonCodec, Space as Room, SerializeMessage, SessionState, ShardCache, ShardClient, SharedSpaceClient, SnapshotNamespace, Space, SpaceCache, SpaceKeyring, SpaceNamespace, SpacePacketCipher, SpaceSignaler, StorageNamespace, SyncEngine, VaultUnavailableError, WSTransport, WebRtcTransport, WorkerEngineHost, ZERO_HLC, ZkAuth, buildCommitment, canonicalUserCode, clearDeviceIdentity, compareHlc, compilePrograms, configureDeviceStore, createPasskeyWithPrf, decodeFromHex, decorators, decryptAesGcm, defaultCircuitUrls, defaultRpId, defaultSessionStore, deleteBeatsWrite, deleteRegister, deriveAesKeyFromPassphrase, deriveBitsHkdf, deriveIdentity, deriveIdentityFromSeed, deriveMasterSeedFromPassword, deviceFingerprint, deviceIdentityIsEphemeral, deviceIdentityKey, ejectAgentPrompt, ejectAgentTools, emptyMap, emptyRegister, encodeToHex, encryptAesGcm, evaluatePasskeyPrf, exportPublicKeyBase64, exportPublicKeyHex, formatUserCode, generateAuthProof, generateDevicePairingKeypair, generatePkce, getMuhkooAppDescriptor, getSubtle, hasDeviceIdentity, initBn128Wasm, initRsWasm, initializeCircuits, isNewer, isOfflineCapable, isP2pCapable, isProvisional, loadDeviceIdentity, manifestToStat, materializeRow, mergeMap, mergeMessage, mergeRegister, messageKey, pack, padHandle, pairingVerificationCode, passkeyPrfCapable, passkeySupported, persistDeviceIdentity, poseidonHash, protocol, provisionalHandle, quickVerify, randomBytes, randomState, rpIdUsableForOrigin, sealSeed, sealSeedToDevice, shardHash, signMessage, stableStringify, toField, tombstoneRow, unpack, unsealSeed, unsealSeedFromDevice, unwrapWithPassphrase, verify, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase, writeBeatsTombstone, writeColumns, writeRegister };
|
|
7058
|
+
export { ACCESS_TOKEN_SCOPES, AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES, AccessTokensNamespace, AgentsNamespace, AuthClient, AuthNamespace, AuthPublicInput, Authenticator, BlockEngine, BroadcastChannel, BroadcastChannelEvents, ChannelExistsError, ChannelNotFoundError, ChunkCipher, Client, ConnectivityManager, DEFAULT_AUTH_BASE_URL, DEFAULT_BASE_URL, DEFAULT_FN_HOST_SUFFIX, DEVICE_IDENTITY_STORAGE_KEY, DEVICE_KEY_DB_NAME, DbCache, DevicePairingError, DeviceStoreUnavailableError, DoubleRatchet, DoubleRatchetCipher, DoubleRatchetManager, EncryptedSession, EventCore, EventCoreEvents, Field, Field as FieldElement, FileStorage, FunctionsNamespace, HLC, HashKnowledge, HostedAuth, HttpClient, HttpError, IndexedDbStore, KEEPER_MEMBER_ID, KeyStore, KeyringClient, KvCache, KvNamespace, LocalEngineHost, LocalStorageSessionStore, MemorySessionStore, Message, Message as MessageDefault, MessageNamespace, MuhkooAgent, MuhkooDB, MuhkooFunction, MuhkooSpace, NoopStore, OfflineLockedError, OfflineManager, OutboundQueue, P2P_SUBJECT, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, PBKDF2_DEFAULT_ITERATIONS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PasskeyOriginError, PeerExchange, PeerNetwork, PersonalSpaceClient, Poseidon, PreimagePoK, ReauthRequiredError, ReedSolomonCodec, Space as Room, SerializeMessage, SessionState, ShardCache, ShardClient, SharedSpaceClient, SnapshotNamespace, Space, SpaceCache, SpaceKeyring, SpaceNamespace, SpacePacketCipher, SpaceSignaler, StorageNamespace, SyncEngine, VaultUnavailableError, WSTransport, WebRtcTransport, WorkerEngineHost, ZERO_HLC, ZkAuth, buildCommitment, canonicalUserCode, clearDeviceIdentity, compareHlc, compilePrograms, configureDeviceStore, createPasskeyWithPrf, decodeFromHex, decorators, decryptAesGcm, defaultCircuitUrls, defaultRpId, defaultSessionStore, deleteBeatsWrite, deleteRegister, deriveAesKeyFromPassphrase, deriveBitsHkdf, deriveIdentity, deriveIdentityFromSeed, deriveMasterSeedFromPassword, deviceFingerprint, deviceIdentityIsEphemeral, deviceIdentityKey, ejectAgentPrompt, ejectAgentTools, emptyMap, emptyRegister, encodeToHex, encryptAesGcm, evaluatePasskeyPrf, exportPublicKeyBase64, exportPublicKeyHex, formatUserCode, generateAuthProof, generateDevicePairingKeypair, generatePkce, getMuhkooAppDescriptor, getSubtle, hasDeviceIdentity, initBn128Wasm, initRsWasm, initializeCircuits, isNewer, isOfflineCapable, isP2pCapable, isProvisional, loadDeviceIdentity, manifestToStat, materializeRow, mergeMap, mergeMessage, mergeRegister, messageKey, pack, padHandle, pairingVerificationCode, passkeyPrfCapable, passkeySupported, passkeyUsableFromOrigin, persistDeviceIdentity, poseidonHash, protocol, provisionalHandle, quickVerify, randomBytes, randomState, rpIdUsableForOrigin, sealSeed, sealSeedToDevice, shardHash, signMessage, stableStringify, toField, tombstoneRow, unpack, unsealSeed, unsealSeedFromDevice, unwrapWithPassphrase, verify, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase, writeBeatsTombstone, writeColumns, writeRegister };
|
|
6636
7059
|
export type { ACL, ACLEntry, AccessTokenInfo, AccessTokensNamespaceDeps, AgentConfig, AgentCreateInput, AgentDbToolMode, AgentProvisioned, AgentScopeOpts, AgentSkill, AgentToolsConfig, AgentTrigger, AgentTriggerType, AgentUpdateInput, AgentsNamespaceDeps, AttachedPeerNetwork, AuthClientOptions, AuthKeyPair, AuthSuccess, AuthToken, AuthType, AuthUser, BlockStore, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, CachedSpaceMessage, ChannelLike, ChunkKeyMaterial, ChunkManifest, CipherFrame, CipherMessage, CipherMessageHeader, CircuitBufferConfig, CircuitUrls, ClientOptions, ConnectivityOptions, ConnectivityState, CreateAccessTokenInput, CreatedAccessToken, DbQueryPage, DehydratedKeypair, DehydratedKeys, DeviceBlobStore, DeviceKeyVault, DevicePairingErrorReason, DevicePairingKeypair, DevicePairingPoll, DevicePairingRequest, DevicePairingSession, DoubleRatchetCipherDeps, ECDHCurve, EncodeResult, EngineHandle, EngineHost, EphemeralEvent, EpochKeyProvider, FileManifest, FileNamespaceDeps, FileStat, FileStorageOptions, FunctionCaps, FunctionConfig, FunctionDeployInput, FunctionInvokeOptions, FunctionScopeOpts, FunctionTrigger, FunctionTriggerType, FunctionTriggers, FunctionUpdateInput, FunctionsNamespaceDeps, Groth16Proof, Hasher, HlcParts, HlcState, HostedAuthDeps, HttpClientOptions, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, KeyringClientDeps, KeyringTransport, KvEntry, KvNamespaceDeps, LoginOptions, LwwMap, LwwRegister, MessageBody, MessageDeletedEvent, MessageEntry, MessageEvent, MessageHeaders, MessageNamespaceDeps, MessageOp, MessageOptions, MessageSubscription, MuhkooAgentMeta, MuhkooAgentToolsConfig, MuhkooAppDescriptor, MuhkooDBAccess, MuhkooDBMeta, MuhkooFunctionMeta, MuhkooKeystoreBridge, MuhkooMessageEvent, MuhkooSpaceMeta, OAuthProvider, OfflineEntry, OfflineManagerDeps, OfflineStore, OutSink, PacketCipher, PacketHeaders, PacketOptions, PairedDevice, Participant, PasskeyEnrollment, PeerBlockSource, PeerExchangeOptions, PeerId, PeerNetworkOptions, PeerTransport, Permission, PermissionCheckRequest, PermissionCheckResult, PersistedDeviceIdentity, PersonalSpaceClientOptions, Pkce, PublicKeyJWK, QueueEntry, RatchetState, ReceiveResult, RegisterParams, Replayer, Role, SpaceDeps as RoomDeps, SpaceFileMetadata as RoomFileMetadata, Scope, SealedHandoff, SealedHeaders, Session, SessionOptions, SessionStore, SetOptions, ShardByteCache, ShardClientOptions, SharedSpaceClientOptions, SignalEnvelope, SignalKind, SignalingSpace, SnapshotNamespaceDeps, SnarkProof, SpaceChannelLike, SpaceCursor, SpaceDeps, SpaceFileMetadata, SpaceKeyCache, SpaceKeyringDeps, SpaceMessageEvent, SpaceNamespaceDeps, SpaceOfflineAdapter, StartDevicePairingOptions, StorageChangeEvent, StoreName, StoredSession, Subscription, UserIdentity, VaultFactor, VerificationKey, WSMessage, WSMessageType, WSTransportOptions, WaitForDevicePairingOptions, WebRtcTransportOptions, WrappedPayload, WriteFileInput, WriteFileOptions, WriteToShardsInput, ZkAuthDeps, ZkAuthenticateRequest, ZkChallengeResponse, ZkCompiled, ZkIdentity, ZkRegisterRequest, ZkRegisterResponse };
|