@muhkoo/connect 0.15.0-alpha.10 → 0.15.0-alpha.12
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/README.md +45 -2
- package/dist/browser/index.js +4998 -1261
- package/dist/browser/index.js.map +1 -1
- package/dist/connect.d.ts +1384 -148
- package/dist/connect.workers.d.ts +306 -2
- package/dist/server/index.js +4998 -1261
- package/dist/server/index.js.map +1 -1
- package/dist/workers/index.js +325 -1
- package/dist/workers/index.js.map +1 -1
- package/package.json +1 -1
package/dist/connect.d.ts
CHANGED
|
@@ -1152,6 +1152,310 @@ declare class PaymentRequiredError extends HttpError {
|
|
|
1152
1152
|
constructor(message: string, code: PaymentRequiredCode, body?: unknown, upgradeUrl?: string);
|
|
1153
1153
|
}
|
|
1154
1154
|
|
|
1155
|
+
/**
|
|
1156
|
+
* Wire types for shared folders. These mirror the accelerator's `/api/shares` JSON
|
|
1157
|
+
* (`ShareInfo` in the accelerator's `durable-objects/space/share.ts`).
|
|
1158
|
+
*/
|
|
1159
|
+
type ShareKind = "public" | "private";
|
|
1160
|
+
/** Who may change a file: `own` = its uploader and the owner; `any` = any member (private shares only). */
|
|
1161
|
+
type EditPolicy = "own" | "any";
|
|
1162
|
+
interface ShareInfo {
|
|
1163
|
+
kind: ShareKind;
|
|
1164
|
+
ownerUsername: string;
|
|
1165
|
+
/** Storage cap in bytes, or null for no cap. */
|
|
1166
|
+
limitBytes: number | null;
|
|
1167
|
+
usedBytes: number;
|
|
1168
|
+
editPolicy: EditPolicy;
|
|
1169
|
+
name: string;
|
|
1170
|
+
/** Set once the share was rotated into another Space; follow `successor`. */
|
|
1171
|
+
closed: {
|
|
1172
|
+
successor: string;
|
|
1173
|
+
at: number;
|
|
1174
|
+
} | null;
|
|
1175
|
+
/** The member list (usernames). */
|
|
1176
|
+
members: string[];
|
|
1177
|
+
/**
|
|
1178
|
+
* Display names by username, for uploaders and admitted members: label files by their `owner` with it. After a
|
|
1179
|
+
* rotation it also holds uploaders not (yet) re-admitted, so it is not the member list.
|
|
1180
|
+
*/
|
|
1181
|
+
names: Record<string, string>;
|
|
1182
|
+
}
|
|
1183
|
+
/** One row of `GET /api/shares`. */
|
|
1184
|
+
interface ShareSummary {
|
|
1185
|
+
spaceId: string;
|
|
1186
|
+
kind: ShareKind;
|
|
1187
|
+
owner: string;
|
|
1188
|
+
name: string;
|
|
1189
|
+
}
|
|
1190
|
+
/** The password verifier the server stores for a public share (`proof` is derived from it). */
|
|
1191
|
+
type PasswordVerifier = {
|
|
1192
|
+
salt: string;
|
|
1193
|
+
iterations: number;
|
|
1194
|
+
verifier: string;
|
|
1195
|
+
};
|
|
1196
|
+
/** `GET /api/shares/:spaceId/public`: what a guest needs before being admitted (app key only, no session). */
|
|
1197
|
+
interface SharePublicInfo {
|
|
1198
|
+
kind: "public";
|
|
1199
|
+
name: string;
|
|
1200
|
+
ownerUsername: string;
|
|
1201
|
+
password: {
|
|
1202
|
+
salt: string;
|
|
1203
|
+
iterations: number;
|
|
1204
|
+
};
|
|
1205
|
+
closed: {
|
|
1206
|
+
successor: string;
|
|
1207
|
+
at: number;
|
|
1208
|
+
} | null;
|
|
1209
|
+
}
|
|
1210
|
+
interface CreateShareBody {
|
|
1211
|
+
spaceId: string;
|
|
1212
|
+
kind: ShareKind;
|
|
1213
|
+
name: string;
|
|
1214
|
+
limitBytes: number | null;
|
|
1215
|
+
editPolicy: EditPolicy;
|
|
1216
|
+
password?: PasswordVerifier;
|
|
1217
|
+
}
|
|
1218
|
+
/** `POST /api/shares/:spaceId/admit`, sent with the signed-in account's session. */
|
|
1219
|
+
interface ShareAdmitBody {
|
|
1220
|
+
/** `passwordProof(password, salt, iterations)` with the share's public salt and iterations. */
|
|
1221
|
+
proof: string;
|
|
1222
|
+
/** The display name shown next to this member's uploads: 1–40 characters after trimming, no control characters. */
|
|
1223
|
+
name: string;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Typed refusals from the shares API. Each extends {@link HttpError}, so code that only knows `HttpError` still
|
|
1228
|
+
* sees the status and body. Codes are the accelerator's wire contract.
|
|
1229
|
+
*/
|
|
1230
|
+
|
|
1231
|
+
/** 402 `share_full`: the share is at its storage cap. */
|
|
1232
|
+
declare class ShareFullError extends HttpError {
|
|
1233
|
+
readonly limitBytes: number;
|
|
1234
|
+
readonly usedBytes: number;
|
|
1235
|
+
/**
|
|
1236
|
+
* How many items of a `Share.writeMany` were not written (the refused one and every one after it). The
|
|
1237
|
+
* server's body has no such field, so it is 0 on an error straight from the wire.
|
|
1238
|
+
*/
|
|
1239
|
+
readonly refused: number;
|
|
1240
|
+
constructor(message: string, limitBytes: number, usedBytes: number,
|
|
1241
|
+
/**
|
|
1242
|
+
* How many items of a `Share.writeMany` were not written (the refused one and every one after it). The
|
|
1243
|
+
* server's body has no such field, so it is 0 on an error straight from the wire.
|
|
1244
|
+
*/
|
|
1245
|
+
refused: number, body?: unknown);
|
|
1246
|
+
}
|
|
1247
|
+
/** 409 `share_closed`: the share was rotated; use `successor` instead. */
|
|
1248
|
+
declare class ShareClosedError extends HttpError {
|
|
1249
|
+
readonly successor: string;
|
|
1250
|
+
constructor(message: string, successor: string, body?: unknown);
|
|
1251
|
+
}
|
|
1252
|
+
/** 403 `share_password`: wrong password. */
|
|
1253
|
+
declare class SharePasswordError extends HttpError {
|
|
1254
|
+
constructor(message: string, body?: unknown);
|
|
1255
|
+
}
|
|
1256
|
+
/** 429 `share_password_rate`: too many wrong passwords. */
|
|
1257
|
+
declare class SharePasswordRateError extends HttpError {
|
|
1258
|
+
readonly retryAfterSeconds: number;
|
|
1259
|
+
constructor(message: string, retryAfterSeconds: number, body?: unknown);
|
|
1260
|
+
}
|
|
1261
|
+
/** 403 `share_member_limit`: the share holds as many members as it allows. */
|
|
1262
|
+
declare class ShareMemberLimitError extends HttpError {
|
|
1263
|
+
constructor(message: string, body?: unknown);
|
|
1264
|
+
}
|
|
1265
|
+
/** 409 `share_space_not_empty`: only an empty Space can become a share. */
|
|
1266
|
+
declare class ShareSpaceNotEmptyError extends HttpError {
|
|
1267
|
+
constructor(message: string, body?: unknown);
|
|
1268
|
+
}
|
|
1269
|
+
/** 409 `share_space_not_ready`: the Space has no `/metadata` yet; create the Space before making it a share. */
|
|
1270
|
+
declare class ShareSpaceNotReadyError extends HttpError {
|
|
1271
|
+
constructor(message: string, body?: unknown);
|
|
1272
|
+
}
|
|
1273
|
+
/** 409 `rotation_mismatch`: a retried rotation asked for other settings than the one in progress. */
|
|
1274
|
+
declare class RotationMismatchError extends HttpError {
|
|
1275
|
+
constructor(message: string, body?: unknown);
|
|
1276
|
+
}
|
|
1277
|
+
/** 409 `rotation_in_progress`: another rotation of this share won; `successor` is its new Space. */
|
|
1278
|
+
declare class RotationInProgressError extends HttpError {
|
|
1279
|
+
readonly successor: string;
|
|
1280
|
+
constructor(message: string, successor: string, body?: unknown);
|
|
1281
|
+
}
|
|
1282
|
+
/**
|
|
1283
|
+
* A rotation (`changePassword` / `removeMember`) claimed `newSpaceId` but its adopt did not finish (network failure
|
|
1284
|
+
* or server error, retried). It is kept on this device: call the same rotation again, or `shares.resumeRotation`,
|
|
1285
|
+
* to finish it into the SAME Space. No other rotation of this share starts until it does.
|
|
1286
|
+
*/
|
|
1287
|
+
declare class RotationIncompleteError extends Error {
|
|
1288
|
+
readonly from: string;
|
|
1289
|
+
readonly newSpaceId: string;
|
|
1290
|
+
readonly cause?: unknown | undefined;
|
|
1291
|
+
constructor(from: string, newSpaceId: string, cause?: unknown | undefined);
|
|
1292
|
+
}
|
|
1293
|
+
/** A guest recovery code that does not parse (expected `<username>:<words>`). */
|
|
1294
|
+
declare class InvalidRecoveryCodeError extends Error {
|
|
1295
|
+
constructor(message?: string);
|
|
1296
|
+
}
|
|
1297
|
+
/** `restoreGuest` would replace another guest's login kept on this device; pass `{ replace: true }` to do so. */
|
|
1298
|
+
declare class GuestLoginConflictError extends Error {
|
|
1299
|
+
readonly existing: string;
|
|
1300
|
+
constructor(existing: string);
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* The typed error for a refused response, or null when it is not a share refusal (the caller then throws what it
|
|
1304
|
+
* threw before). `body` is the parsed JSON or the raw response text. `retryAfterSeconds` is the `Retry-After`
|
|
1305
|
+
* header, used for a 429.
|
|
1306
|
+
*/
|
|
1307
|
+
declare function shareErrorFrom(status: number, body: unknown, retryAfterSeconds?: number): Error | null;
|
|
1308
|
+
|
|
1309
|
+
/**
|
|
1310
|
+
* `HttpClient` — the one place the unified {@link Client} talks to the
|
|
1311
|
+
* accelerator over HTTP.
|
|
1312
|
+
*
|
|
1313
|
+
* Every request carries two independent credentials:
|
|
1314
|
+
* - the **app key** (`mk_…`) on `X-Muhkoo-Key` — resolves the app /
|
|
1315
|
+
* developer / env context the accelerator uses for routing + billing;
|
|
1316
|
+
* - the **user session token** on `X-Muhkoo-Session` (when a user is
|
|
1317
|
+
* logged in) — the accelerator validates it and injects a trusted
|
|
1318
|
+
* `X-Muhkoo-User-Context` downstream so per-user spaces can authorize
|
|
1319
|
+
* the request without a fresh Groth16 proof.
|
|
1320
|
+
*
|
|
1321
|
+
* `X-Muhkoo-Key` is used (rather than `Authorization: Bearer`) because it is
|
|
1322
|
+
* a non-forbidden header that skips the CORS preflight in browsers.
|
|
1323
|
+
*
|
|
1324
|
+
* The class exposes a header-injecting {@link fetch} that can be handed to
|
|
1325
|
+
* lower-level building blocks (`AuthClient`, `PersonalSpaceClient`) so they
|
|
1326
|
+
* keep owning their own wire shapes while still getting the credentials, plus
|
|
1327
|
+
* convenience JSON helpers (`get`/`post`/`del`) for code that talks to the
|
|
1328
|
+
* accelerator directly.
|
|
1329
|
+
*/
|
|
1330
|
+
interface HttpClientOptions {
|
|
1331
|
+
/** Absolute URL of the accelerator worker (trailing slash optional). */
|
|
1332
|
+
baseUrl: string;
|
|
1333
|
+
/**
|
|
1334
|
+
* App / publishable key, e.g. `mk_test_pk_…`. Sent on every request as
|
|
1335
|
+
* `X-Muhkoo-Key` when present. Transitionally optional (auth + personal
|
|
1336
|
+
* storage still function without it), but the product direction is to
|
|
1337
|
+
* REQUIRE it — it attributes traffic for billing/metering and authorizes
|
|
1338
|
+
* shared-space (messaging) websockets.
|
|
1339
|
+
*/
|
|
1340
|
+
apiKey?: string;
|
|
1341
|
+
/**
|
|
1342
|
+
* A scoped, expiring **access token** (`mk_<env>_at_…`) — the non-ZK
|
|
1343
|
+
* machine-to-machine credential. It resolves through the SAME accelerator
|
|
1344
|
+
* path as an app key and rides the same `X-Muhkoo-Key` header; when present
|
|
1345
|
+
* it takes precedence over {@link apiKey}. Use it for server-side / CI
|
|
1346
|
+
* callers that shouldn't carry the app's publishable key.
|
|
1347
|
+
*/
|
|
1348
|
+
accessToken?: string;
|
|
1349
|
+
/** Returns the current user session token, or `null` when logged out. */
|
|
1350
|
+
getSessionToken?: () => string | null;
|
|
1351
|
+
/** Custom fetch — defaults to `globalThis.fetch`. */
|
|
1352
|
+
fetch?: typeof fetch;
|
|
1353
|
+
/**
|
|
1354
|
+
* Called when a token-gated request comes back `401` (stale/expired
|
|
1355
|
+
* session). Should attempt to silently re-establish a session and resolve
|
|
1356
|
+
* `true` if it succeeded (the request is then retried once with the fresh
|
|
1357
|
+
* token) or `false` if it couldn't (the `401` propagates as an
|
|
1358
|
+
* {@link HttpError}). Wired by {@link Client} to `auth.zk.recover()`.
|
|
1359
|
+
*
|
|
1360
|
+
* Only consulted by the JSON helpers (`get`/`post`/`del`) and
|
|
1361
|
+
* {@link HttpClient.fetchWithRecovery}; the raw {@link fetch} passes 401s
|
|
1362
|
+
* straight through so the auth wire calls that power recovery itself
|
|
1363
|
+
* can't recurse.
|
|
1364
|
+
*/
|
|
1365
|
+
onUnauthorized?: () => Promise<boolean>;
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
declare class HttpClient {
|
|
1369
|
+
readonly baseUrl: string;
|
|
1370
|
+
/** Origin of {@link baseUrl} — credentials are only attached same-origin. */
|
|
1371
|
+
private readonly baseOrigin;
|
|
1372
|
+
private readonly apiKey;
|
|
1373
|
+
/** Scoped machine access token — takes precedence over {@link apiKey} on `X-Muhkoo-Key`. */
|
|
1374
|
+
private readonly accessToken;
|
|
1375
|
+
private readonly getSessionToken;
|
|
1376
|
+
private readonly onUnauthorized;
|
|
1377
|
+
private readonly fetchFn;
|
|
1378
|
+
constructor(opts: HttpClientOptions);
|
|
1379
|
+
/**
|
|
1380
|
+
* A `fetch`-compatible function that injects the app key + session token
|
|
1381
|
+
* headers. Hand this to `AuthClient` / `PersonalSpaceClient` so they pick
|
|
1382
|
+
* up credentials without knowing about them.
|
|
1383
|
+
*/
|
|
1384
|
+
readonly fetch: typeof fetch;
|
|
1385
|
+
/**
|
|
1386
|
+
* {@link fetch} with the JSON helpers' stale-session recovery: a 401 on a
|
|
1387
|
+
* request made while a session token is held runs `onUnauthorized` once
|
|
1388
|
+
* and, if that recovered, replays the request once with the fresh token.
|
|
1389
|
+
* The final response is returned whatever its status, never thrown. The
|
|
1390
|
+
* replay re-sends `init` as given, so its body must be re-sendable (a
|
|
1391
|
+
* string or bytes, not a stream).
|
|
1392
|
+
*/
|
|
1393
|
+
readonly fetchWithRecovery: typeof fetch;
|
|
1394
|
+
/**
|
|
1395
|
+
* A client for the same accelerator and key that never sends a session token and never recovers one. For routes
|
|
1396
|
+
* that need only the app key (a public share's pre-admission info).
|
|
1397
|
+
*/
|
|
1398
|
+
withoutSession(): HttpClient;
|
|
1399
|
+
/** True when `input` resolves to {@link baseOrigin} (relative URLs always do). */
|
|
1400
|
+
private isSameOrigin;
|
|
1401
|
+
get<T = unknown>(path: string): Promise<T>;
|
|
1402
|
+
post<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
1403
|
+
put<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
1404
|
+
patch<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
1405
|
+
del<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
1406
|
+
private request;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
/**
|
|
1410
|
+
* `SharesClient` — the thin HTTP layer over the accelerator's `/api/shares` routes. It owns paths, verbs and error
|
|
1411
|
+
* mapping and nothing else; the `Share` object and `client.shares` build on it.
|
|
1412
|
+
*
|
|
1413
|
+
* Every call but `publicInfo` carries the app key and the signed-in session (with the usual stale-session recovery),
|
|
1414
|
+
* including `admit`: a public share's guest is an ordinary account. `publicInfo` needs only the app key and never
|
|
1415
|
+
* sends a session.
|
|
1416
|
+
*/
|
|
1417
|
+
|
|
1418
|
+
declare class SharesClient {
|
|
1419
|
+
private readonly http;
|
|
1420
|
+
private readonly keyOnlyHttp;
|
|
1421
|
+
constructor(http: HttpClient);
|
|
1422
|
+
create(body: CreateShareBody): Promise<ShareInfo>;
|
|
1423
|
+
list(): Promise<ShareSummary[]>;
|
|
1424
|
+
info(spaceId: string): Promise<ShareInfo>;
|
|
1425
|
+
update(spaceId: string, patch: {
|
|
1426
|
+
limitBytes?: number | null;
|
|
1427
|
+
editPolicy?: EditPolicy;
|
|
1428
|
+
}): Promise<ShareInfo>;
|
|
1429
|
+
/** A public share's name, owner and password salt, read before admission. Publishable key only; never the verifier. */
|
|
1430
|
+
publicInfo(spaceId: string): Promise<SharePublicInfo>;
|
|
1431
|
+
/**
|
|
1432
|
+
* Admit the signed-in account to a public share by proving its password. Afterwards the account is a member:
|
|
1433
|
+
* it sends its own `/keyring/join-request`. Re-admitting the same account only updates its name.
|
|
1434
|
+
*/
|
|
1435
|
+
admit(spaceId: string, body: ShareAdmitBody): Promise<void>;
|
|
1436
|
+
removeMember(spaceId: string, username: string): Promise<void>;
|
|
1437
|
+
/** Rotate: `from` is the old share, `newSpaceId` the Space the client made and seeded. */
|
|
1438
|
+
adopt(newSpaceId: string, body: {
|
|
1439
|
+
from: string;
|
|
1440
|
+
password?: PasswordVerifier;
|
|
1441
|
+
remove?: string[];
|
|
1442
|
+
}): Promise<ShareInfo>;
|
|
1443
|
+
private send;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
/**
|
|
1447
|
+
* Public-share password proof. The password never leaves the device: the guest sends
|
|
1448
|
+
* `proof = base64(PBKDF2-SHA256(password, salt, iterations, 32 bytes))` and the server stores
|
|
1449
|
+
* `verifier = base64(SHA-256(proof bytes))`. The salt is an opaque string chosen at creation time;
|
|
1450
|
+
* both sides use its UTF-8 bytes.
|
|
1451
|
+
*/
|
|
1452
|
+
|
|
1453
|
+
declare const SHARE_PASSWORD_ITERATIONS = 310000;
|
|
1454
|
+
/** What a guest sends to prove it knows the password. */
|
|
1455
|
+
declare function passwordProof(password: string, salt: string, iterations: number): Promise<string>;
|
|
1456
|
+
/** What the share owner registers at creation: a fresh salt and the verifier for `password`. */
|
|
1457
|
+
declare function newPasswordVerifier(password: string): Promise<PasswordVerifier>;
|
|
1458
|
+
|
|
1155
1459
|
/**
|
|
1156
1460
|
* Cloudflare-Workers-compatible Groth16 ZK proof verifier.
|
|
1157
1461
|
*
|
|
@@ -1388,6 +1692,13 @@ type OprfProtocol = typeof OPRF_PROTOCOL_BASE | typeof OPRF_PROTOCOL_POPRF;
|
|
|
1388
1692
|
* one meant regex-matching a sentence the server is free to reword. See
|
|
1389
1693
|
* `VaultUnavailableError`, which still does exactly that for rate limits.
|
|
1390
1694
|
*/
|
|
1695
|
+
/** One Google account matched: the single-use token, the Google `sub`, and (when the lookup named it) the username. */
|
|
1696
|
+
interface GoogleVerifyOne {
|
|
1697
|
+
verifyToken: string;
|
|
1698
|
+
sub: string;
|
|
1699
|
+
emailHint: string | null;
|
|
1700
|
+
username?: string;
|
|
1701
|
+
}
|
|
1391
1702
|
declare class AuthHttpError extends Error {
|
|
1392
1703
|
readonly label: string;
|
|
1393
1704
|
readonly status: number;
|
|
@@ -1521,11 +1832,21 @@ declare class AuthClient {
|
|
|
1521
1832
|
googleVerify(opts: {
|
|
1522
1833
|
idToken: string;
|
|
1523
1834
|
token?: string;
|
|
1835
|
+
username: string;
|
|
1836
|
+
}): Promise<GoogleVerifyOne>;
|
|
1837
|
+
googleVerify(opts: {
|
|
1838
|
+
idToken: string;
|
|
1839
|
+
token: string;
|
|
1524
1840
|
username?: string;
|
|
1525
|
-
}): Promise<
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1841
|
+
}): Promise<GoogleVerifyOne>;
|
|
1842
|
+
googleVerify(opts: {
|
|
1843
|
+
idToken: string;
|
|
1844
|
+
}): Promise<GoogleVerifyOne | {
|
|
1845
|
+
usernames: string[];
|
|
1846
|
+
}>;
|
|
1847
|
+
/** Is `redirectUri` registered for `appId`? (Public; used before sending a user to a logout target.) */
|
|
1848
|
+
redirectCheck(appId: string, redirectUri: string): Promise<{
|
|
1849
|
+
allowed: boolean;
|
|
1529
1850
|
}>;
|
|
1530
1851
|
/** Mint a single-use authorization code for an app (called by the hosted page; session-authed). */
|
|
1531
1852
|
grant(token: string, body: {
|
|
@@ -2936,6 +3257,160 @@ declare class ReedSolomonCodec {
|
|
|
2936
3257
|
*/
|
|
2937
3258
|
declare function initRsWasm(wasmModule?: WebAssembly.Module): Promise<void>;
|
|
2938
3259
|
|
|
3260
|
+
/**
|
|
3261
|
+
* `Share` — one shared folder: a folder view over the share Space's file records and the file operations on it.
|
|
3262
|
+
*
|
|
3263
|
+
* The folder tree is built from each file record's `path` (`"a/c/d.jpg"`). An empty folder is a zero-byte record
|
|
3264
|
+
* of type {@link SHARE_DIR_TYPE}; a folder that holds files needs no record of its own.
|
|
3265
|
+
*
|
|
3266
|
+
* Files use the Space file store (`/api/spaces/:id/files`) and the Space's own shard route
|
|
3267
|
+
* (`PUT /api/spaces/:id/shards/:hash`), which is where a share's limit is enforced and its owner billed. The
|
|
3268
|
+
* server stamps each file's uploader on its first write and lists it as `owner`; renaming re-posts the same file
|
|
3269
|
+
* id, so the uploader never changes.
|
|
3270
|
+
*
|
|
3271
|
+
* Every call carries the app key and the signed-in user's session (with the client's stale-session recovery).
|
|
3272
|
+
*/
|
|
3273
|
+
|
|
3274
|
+
/** The MIME type of an empty-folder record. */
|
|
3275
|
+
declare const SHARE_DIR_TYPE = "inode/directory";
|
|
3276
|
+
interface ShareEntry {
|
|
3277
|
+
/** Full path inside the share, no leading slash (`"a/c/d.jpg"`). */
|
|
3278
|
+
path: string;
|
|
3279
|
+
name: string;
|
|
3280
|
+
kind: "file" | "dir";
|
|
3281
|
+
/** Bytes; for a folder, the total of the files under it. */
|
|
3282
|
+
size: number;
|
|
3283
|
+
/** Last modified (ms epoch); for a folder, the newest record under it. */
|
|
3284
|
+
mtime: number;
|
|
3285
|
+
/** Who uploaded it (a username). `""` for a legacy file with no recorded uploader, or a folder with no record of its own. */
|
|
3286
|
+
uploader: string;
|
|
3287
|
+
/** The uploader's display name from `ShareInfo.names`, else the username; `"Unknown"` for a legacy file. */
|
|
3288
|
+
uploaderName: string;
|
|
3289
|
+
/**
|
|
3290
|
+
* Whether the server would let the caller change or delete it (it mirrors the server's `canChangeFile`). For a
|
|
3291
|
+
* folder: whether every record under it is changeable, since deleting a folder deletes them all.
|
|
3292
|
+
*/
|
|
3293
|
+
canChange: boolean;
|
|
3294
|
+
}
|
|
3295
|
+
interface ShareOptions {
|
|
3296
|
+
/** The app's HTTP client (app key and the signed-in session). */
|
|
3297
|
+
http: HttpClient;
|
|
3298
|
+
spaceId: string;
|
|
3299
|
+
/** The signed-in caller's username. */
|
|
3300
|
+
me: string;
|
|
3301
|
+
/** A pre-compiled Reed-Solomon module, for runtimes without the bundled loader (Node tests, Workers). */
|
|
3302
|
+
rsWasmModule?: WebAssembly.Module;
|
|
3303
|
+
}
|
|
3304
|
+
/** A file for {@link Share.adopt}: content already stored, named by its manifest. */
|
|
3305
|
+
interface ShareAdoptFile {
|
|
3306
|
+
kind: "file";
|
|
3307
|
+
/** Path inside the share. */
|
|
3308
|
+
path: string;
|
|
3309
|
+
manifest: FileManifest;
|
|
3310
|
+
/** Unique among the items and stable across runs (the VFS file id): names the record when the manifest's id is taken. */
|
|
3311
|
+
key: string;
|
|
3312
|
+
}
|
|
3313
|
+
/** An item for {@link Share.adopt}: a file, or an empty folder. */
|
|
3314
|
+
type ShareAdoptItem = ShareAdoptFile | {
|
|
3315
|
+
kind: "folder";
|
|
3316
|
+
path: string;
|
|
3317
|
+
};
|
|
3318
|
+
declare class Share {
|
|
3319
|
+
readonly spaceId: string;
|
|
3320
|
+
private readonly http;
|
|
3321
|
+
private readonly me;
|
|
3322
|
+
private readonly files;
|
|
3323
|
+
constructor(opts: ShareOptions);
|
|
3324
|
+
/** The share record (`GET /api/shares/:id`). */
|
|
3325
|
+
info(): Promise<ShareInfo>;
|
|
3326
|
+
/** The entries directly inside `dir` (the root by default): folders first, then by name. */
|
|
3327
|
+
list(dir?: string): Promise<ShareEntry[]>;
|
|
3328
|
+
read(path: string): Promise<Uint8Array>;
|
|
3329
|
+
/**
|
|
3330
|
+
* Upload `data` to `path`, replacing the file already there (same file id, so its uploader is kept; the server
|
|
3331
|
+
* refuses if the caller may not change it). `onProgress` gets the fraction done, 0 to 1.
|
|
3332
|
+
*/
|
|
3333
|
+
write(path: string, data: Blob | Uint8Array, opts?: {
|
|
3334
|
+
type?: string;
|
|
3335
|
+
onProgress?: (n: number) => void;
|
|
3336
|
+
}): Promise<ShareEntry>;
|
|
3337
|
+
/**
|
|
3338
|
+
* Upload several files in order. At the first `share_full` it stops and throws a {@link ShareFullError} whose
|
|
3339
|
+
* `refused` is the number of items not written (that one and every one after it).
|
|
3340
|
+
*/
|
|
3341
|
+
writeMany(items: Array<{
|
|
3342
|
+
path: string;
|
|
3343
|
+
data: Blob | Uint8Array;
|
|
3344
|
+
type?: string;
|
|
3345
|
+
}>): Promise<ShareEntry[]>;
|
|
3346
|
+
/** Make an empty folder: a zero-byte record of type {@link SHARE_DIR_TYPE}. A folder already there is left alone. */
|
|
3347
|
+
mkdir(path: string): Promise<void>;
|
|
3348
|
+
/**
|
|
3349
|
+
* Delete a file, or a folder and every record under it. Nothing there is not an error. Every record is checked
|
|
3350
|
+
* first: if the caller may not change one of them, nothing is deleted.
|
|
3351
|
+
*/
|
|
3352
|
+
delete(path: string): Promise<void>;
|
|
3353
|
+
/**
|
|
3354
|
+
* Move a file or folder by rewriting each record's `path` in place (same file id), so uploaders are unchanged —
|
|
3355
|
+
* except a legacy file with no recorded uploader, which the server stamps to whoever rewrites it, i.e. the
|
|
3356
|
+
* renamer.
|
|
3357
|
+
*
|
|
3358
|
+
* Every record is checked first: if the caller may not change one of them, nothing moves. A folder moves one
|
|
3359
|
+
* record at a time; if that stops part-way (a network failure), the error names what already moved, and
|
|
3360
|
+
* calling the same `rename` again finishes the move.
|
|
3361
|
+
*/
|
|
3362
|
+
rename(from: string, to: string): Promise<void>;
|
|
3363
|
+
/**
|
|
3364
|
+
* Put files whose content is already stored into the share without uploading a byte: each file's existing
|
|
3365
|
+
* manifest is posted to the share's file store at `path` (shards are content-addressed and every Space reads
|
|
3366
|
+
* the same shard store; the server charges the share for the bytes it finds stored). For
|
|
3367
|
+
* `client.shares.shareFolder`, which owns the share; not a general upload path.
|
|
3368
|
+
*
|
|
3369
|
+
* Safe to run again over the same items: a file already in the share at its path with the id it was given
|
|
3370
|
+
* (the manifest's id, or `<manifest id>.<key>` when another file in the share has that one) is not posted
|
|
3371
|
+
* again, and a file that moved inside the folder since moves in the share. `onEach(item, posted, recordId)`
|
|
3372
|
+
* runs after each file is in the share, `posted` false when it was there already, `recordId` the id of the
|
|
3373
|
+
* record that holds it; an error from it stops the run. `beforePost(item, recordId)` runs just before each
|
|
3374
|
+
* record (a file's, or an empty folder's) is posted, so a caller can note what it is about to put in the share
|
|
3375
|
+
* before it is there; an error from it stops the run before that post. Empty folders become folder records
|
|
3376
|
+
* unless something is at or below their path already.
|
|
3377
|
+
*
|
|
3378
|
+
* At the first `share_full` it stops with a {@link ShareFullError} whose `refused` is the number of files
|
|
3379
|
+
* not put in the share.
|
|
3380
|
+
*/
|
|
3381
|
+
adopt(items: ShareAdoptItem[], onEach?: (item: ShareAdoptFile, posted: boolean, recordId: string) => Promise<void>, beforePost?: (item: ShareAdoptItem, recordId: string) => Promise<void>): Promise<void>;
|
|
3382
|
+
/**
|
|
3383
|
+
* Delete the records with these ids that the caller uploaded and `keep` does not keep. For
|
|
3384
|
+
* `client.shares.shareFolder`, taking back what an earlier run of it put in the share that is no longer in the
|
|
3385
|
+
* folder; not a general delete. A record someone else uploaded (the server's stamped uploader is not the
|
|
3386
|
+
* caller) is never touched, nor is an id not in the share. Returns the ids deleted.
|
|
3387
|
+
*/
|
|
3388
|
+
removeAdopted(ids: Iterable<string>, keep?: (record: {
|
|
3389
|
+
id: string;
|
|
3390
|
+
path: string;
|
|
3391
|
+
kind: "file" | "dir";
|
|
3392
|
+
}) => boolean): Promise<string[]>;
|
|
3393
|
+
/** Bytes stored and the limit (null = no limit). */
|
|
3394
|
+
usage(): Promise<{
|
|
3395
|
+
usedBytes: number;
|
|
3396
|
+
limitBytes: number | null;
|
|
3397
|
+
}>;
|
|
3398
|
+
private writeInto;
|
|
3399
|
+
private fileEntry;
|
|
3400
|
+
/** A 403 naming the first of `records` the caller may not change, before anything is sent. */
|
|
3401
|
+
private refuseUnchangeable;
|
|
3402
|
+
/** The server's `canChangeFile`, from the caller's side. */
|
|
3403
|
+
private canChange;
|
|
3404
|
+
private records;
|
|
3405
|
+
private postManifest;
|
|
3406
|
+
private filesBase;
|
|
3407
|
+
/** The app's fetch with the session's stale-session recovery. Bodies here are strings or bytes, so a replay is safe. */
|
|
3408
|
+
private readonly send;
|
|
3409
|
+
/** {@link send} for shard requests: a share refusal (full, closed) is thrown typed; anything else is left to `ShardClient`. */
|
|
3410
|
+
private readonly shardFetch;
|
|
3411
|
+
private json;
|
|
3412
|
+
}
|
|
3413
|
+
|
|
2939
3414
|
/**
|
|
2940
3415
|
* `SessionState` — the in-memory source of truth for "who is signed in" on a
|
|
2941
3416
|
* {@link Client}.
|
|
@@ -3275,6 +3750,15 @@ declare class HostedAuth {
|
|
|
3275
3750
|
prompt?: "login";
|
|
3276
3751
|
returnTo?: string;
|
|
3277
3752
|
}): Promise<string>;
|
|
3753
|
+
/**
|
|
3754
|
+
* (App side) Sign the browser out of the hosted page too, then land on
|
|
3755
|
+
* `redirectUri`. The hosted page only honours a `redirectUri` the app has
|
|
3756
|
+
* registered; any other lands on its own page. Redirects the browser.
|
|
3757
|
+
*/
|
|
3758
|
+
logout(opts: {
|
|
3759
|
+
appId: string;
|
|
3760
|
+
redirectUri: string;
|
|
3761
|
+
}): void;
|
|
3278
3762
|
/**
|
|
3279
3763
|
* (App side) Send the user to centralized account & security management on
|
|
3280
3764
|
* the hosted page (auth.muhkoo.dev/security) — manage passkeys, recovery
|
|
@@ -3555,6 +4039,13 @@ declare class VaultProtocolMismatchError extends Error {
|
|
|
3555
4039
|
declare class DeviceRevokedError extends Error {
|
|
3556
4040
|
constructor();
|
|
3557
4041
|
}
|
|
4042
|
+
/**
|
|
4043
|
+
* `signInWithGoogle` without a username found no Muhkoo account linked to this
|
|
4044
|
+
* Google account. Ask for the username and call again with `{ username }`.
|
|
4045
|
+
*/
|
|
4046
|
+
declare class GoogleNotLinkedError extends Error {
|
|
4047
|
+
constructor();
|
|
4048
|
+
}
|
|
3558
4049
|
/** What the auth methods resolve to — the stable, non-secret user facts. */
|
|
3559
4050
|
interface AuthUser {
|
|
3560
4051
|
username: string;
|
|
@@ -3711,6 +4202,18 @@ declare class ZkAuth {
|
|
|
3711
4202
|
* factor first.
|
|
3712
4203
|
*/
|
|
3713
4204
|
loginWithGoogle(username: string, idToken: string, opts?: LoginOptions): Promise<AuthUser>;
|
|
4205
|
+
private completeGoogleLogin;
|
|
4206
|
+
/**
|
|
4207
|
+
* Sign in with Google, naming no account. One linked account completes the
|
|
4208
|
+
* sign-in; several return `{ chooseAccount }` (call again with `{ username }`);
|
|
4209
|
+
* none throws {@link GoogleNotLinkedError}. With `username` this is
|
|
4210
|
+
* {@link loginWithGoogle}.
|
|
4211
|
+
*/
|
|
4212
|
+
signInWithGoogle(idToken: string, opts?: {
|
|
4213
|
+
username?: string;
|
|
4214
|
+
} & LoginOptions): Promise<AuthUser | {
|
|
4215
|
+
chooseAccount: string[];
|
|
4216
|
+
}>;
|
|
3714
4217
|
/**
|
|
3715
4218
|
* Register a brand-new, **passwordless** account whose only factor is Google.
|
|
3716
4219
|
* A random master seed is generated and wrapped under the Google-gated key;
|
|
@@ -3751,6 +4254,13 @@ declare class ZkAuth {
|
|
|
3751
4254
|
* its PRF, unwraps the master seed → identity → session.
|
|
3752
4255
|
*/
|
|
3753
4256
|
loginWithPasskey(username: string, opts?: LoginOptions): Promise<AuthUser>;
|
|
4257
|
+
/**
|
|
4258
|
+
* Can a passkey unlock `username` from THIS origin? `"usable"`, `"none"` (no
|
|
4259
|
+
* passkey enrolled) or `"other-origin"` (enrolled, but for another host).
|
|
4260
|
+
* The vault answers a decoy for absent accounts, so an unknown username
|
|
4261
|
+
* reads like a real one; callers must still handle a failed prompt.
|
|
4262
|
+
*/
|
|
4263
|
+
passkeyStatus(username: string): Promise<"usable" | "none" | "other-origin">;
|
|
3754
4264
|
/**
|
|
3755
4265
|
* List the user's enrolled login methods (metadata only). Session-authed.
|
|
3756
4266
|
* Gated factors (email/google) carry a `masked` display hint
|
|
@@ -3870,148 +4380,54 @@ declare class ZkAuth {
|
|
|
3870
4380
|
*
|
|
3871
4381
|
* Establishes the ENCRYPTION identity only. It does not authenticate: pair
|
|
3872
4382
|
* it with a session token (`sessionStore`) for calls that need one.
|
|
3873
|
-
*
|
|
3874
|
-
* Treat a persisted seed as the master credential it is. It is not scoped
|
|
3875
|
-
* and cannot be revoked server-side the way a session token can — rotating
|
|
3876
|
-
* it means moving the identity.
|
|
3877
|
-
*/
|
|
3878
|
-
unlockWithSeed(seedBase64: string): void;
|
|
3879
|
-
/** Poseidon commitment for an identity — the value the server stores. */
|
|
3880
|
-
private commitmentFor;
|
|
3881
|
-
/**
|
|
3882
|
-
* Derive the OPRF-gated wrap key for the password factor: `scrypt(password)`
|
|
3883
|
-
* is blinded, evaluated by the server's secret OPRF key (so it can't be
|
|
3884
|
-
* derived offline), unblinded, then HKDF'd into an AES-GCM key.
|
|
3885
|
-
*/
|
|
3886
|
-
private passwordWrapKey;
|
|
3887
|
-
/**
|
|
3888
|
-
* Try to recover the master seed from the password factor.
|
|
3889
|
-
*
|
|
3890
|
-
* Returns `null` only when the vault read SUCCEEDS but the seed can't be
|
|
3891
|
-
* unwrapped — i.e. there's no real factor (a pre-vault/legacy account, whose
|
|
3892
|
-
* read returns a decoy that won't unwrap) or the password is wrong. The caller
|
|
3893
|
-
* then legitimately falls back to the legacy password-derived identity.
|
|
3894
|
-
*
|
|
3895
|
-
* Throws {@link VaultUnavailableError} when the vault itself can't be reached
|
|
3896
|
-
* (network / 5xx / rate-limit) — so a *transient* failure is NOT silently
|
|
3897
|
-
* turned into a legacy fallback (which would surface as "commitment mismatch").
|
|
3898
|
-
*/
|
|
3899
|
-
private tryUnlockSeed;
|
|
3900
|
-
/**
|
|
3901
|
-
* Enroll/replace the password factor for `username` — wraps `seed` under the
|
|
3902
|
-
* OPRF-gated key and stores it (needs a session `token`).
|
|
3903
|
-
*
|
|
3904
|
-
* Retries: this is the step that persists the (otherwise in-memory-only)
|
|
3905
|
-
* master seed. If it fails after a fresh registration the account would be
|
|
3906
|
-
* unrecoverable, so we retry a few times before surfacing the error.
|
|
3907
|
-
*/
|
|
3908
|
-
private enrollPasswordFactor;
|
|
3909
|
-
}
|
|
3910
|
-
/** `client.auth` — the auth namespace. Strategies hang off here. */
|
|
3911
|
-
declare class AuthNamespace {
|
|
3912
|
-
readonly zk: ZkAuth;
|
|
3913
|
-
/** Centralized hosted auth (auth.muhkoo.dev) — `client.auth.hosted.login(...)`. */
|
|
3914
|
-
readonly hosted: HostedAuth;
|
|
3915
|
-
constructor(deps: ZkAuthDeps & {
|
|
3916
|
-
authBaseUrl: string;
|
|
3917
|
-
apiBaseUrl?: string;
|
|
3918
|
-
});
|
|
3919
|
-
/** Convenience pass-through: the currently signed-in user, or `null`. */
|
|
3920
|
-
get user(): AuthUser | null;
|
|
3921
|
-
}
|
|
3922
|
-
|
|
3923
|
-
/**
|
|
3924
|
-
* `HttpClient` — the one place the unified {@link Client} talks to the
|
|
3925
|
-
* accelerator over HTTP.
|
|
3926
|
-
*
|
|
3927
|
-
* Every request carries two independent credentials:
|
|
3928
|
-
* - the **app key** (`mk_…`) on `X-Muhkoo-Key` — resolves the app /
|
|
3929
|
-
* developer / env context the accelerator uses for routing + billing;
|
|
3930
|
-
* - the **user session token** on `X-Muhkoo-Session` (when a user is
|
|
3931
|
-
* logged in) — the accelerator validates it and injects a trusted
|
|
3932
|
-
* `X-Muhkoo-User-Context` downstream so per-user spaces can authorize
|
|
3933
|
-
* the request without a fresh Groth16 proof.
|
|
3934
|
-
*
|
|
3935
|
-
* `X-Muhkoo-Key` is used (rather than `Authorization: Bearer`) because it is
|
|
3936
|
-
* a non-forbidden header that skips the CORS preflight in browsers.
|
|
3937
|
-
*
|
|
3938
|
-
* The class exposes a header-injecting {@link fetch} that can be handed to
|
|
3939
|
-
* lower-level building blocks (`AuthClient`, `PersonalSpaceClient`) so they
|
|
3940
|
-
* keep owning their own wire shapes while still getting the credentials, plus
|
|
3941
|
-
* convenience JSON helpers (`get`/`post`/`del`) for code that talks to the
|
|
3942
|
-
* accelerator directly.
|
|
3943
|
-
*/
|
|
3944
|
-
interface HttpClientOptions {
|
|
3945
|
-
/** Absolute URL of the accelerator worker (trailing slash optional). */
|
|
3946
|
-
baseUrl: string;
|
|
3947
|
-
/**
|
|
3948
|
-
* App / publishable key, e.g. `mk_test_pk_…`. Sent on every request as
|
|
3949
|
-
* `X-Muhkoo-Key` when present. Transitionally optional (auth + personal
|
|
3950
|
-
* storage still function without it), but the product direction is to
|
|
3951
|
-
* REQUIRE it — it attributes traffic for billing/metering and authorizes
|
|
3952
|
-
* shared-space (messaging) websockets.
|
|
3953
|
-
*/
|
|
3954
|
-
apiKey?: string;
|
|
3955
|
-
/**
|
|
3956
|
-
* A scoped, expiring **access token** (`mk_<env>_at_…`) — the non-ZK
|
|
3957
|
-
* machine-to-machine credential. It resolves through the SAME accelerator
|
|
3958
|
-
* path as an app key and rides the same `X-Muhkoo-Key` header; when present
|
|
3959
|
-
* it takes precedence over {@link apiKey}. Use it for server-side / CI
|
|
3960
|
-
* callers that shouldn't carry the app's publishable key.
|
|
3961
|
-
*/
|
|
3962
|
-
accessToken?: string;
|
|
3963
|
-
/** Returns the current user session token, or `null` when logged out. */
|
|
3964
|
-
getSessionToken?: () => string | null;
|
|
3965
|
-
/** Custom fetch — defaults to `globalThis.fetch`. */
|
|
3966
|
-
fetch?: typeof fetch;
|
|
3967
|
-
/**
|
|
3968
|
-
* Called when a token-gated request comes back `401` (stale/expired
|
|
3969
|
-
* session). Should attempt to silently re-establish a session and resolve
|
|
3970
|
-
* `true` if it succeeded (the request is then retried once with the fresh
|
|
3971
|
-
* token) or `false` if it couldn't (the `401` propagates as an
|
|
3972
|
-
* {@link HttpError}). Wired by {@link Client} to `auth.zk.recover()`.
|
|
3973
|
-
*
|
|
3974
|
-
* Only consulted by the JSON helpers (`get`/`post`/`del`) and
|
|
3975
|
-
* {@link HttpClient.fetchWithRecovery}; the raw {@link fetch} passes 401s
|
|
3976
|
-
* straight through so the auth wire calls that power recovery itself
|
|
3977
|
-
* can't recurse.
|
|
3978
|
-
*/
|
|
3979
|
-
onUnauthorized?: () => Promise<boolean>;
|
|
3980
|
-
}
|
|
3981
|
-
|
|
3982
|
-
declare class HttpClient {
|
|
3983
|
-
readonly baseUrl: string;
|
|
3984
|
-
/** Origin of {@link baseUrl} — credentials are only attached same-origin. */
|
|
3985
|
-
private readonly baseOrigin;
|
|
3986
|
-
private readonly apiKey;
|
|
3987
|
-
/** Scoped machine access token — takes precedence over {@link apiKey} on `X-Muhkoo-Key`. */
|
|
3988
|
-
private readonly accessToken;
|
|
3989
|
-
private readonly getSessionToken;
|
|
3990
|
-
private readonly onUnauthorized;
|
|
3991
|
-
private readonly fetchFn;
|
|
3992
|
-
constructor(opts: HttpClientOptions);
|
|
4383
|
+
*
|
|
4384
|
+
* Treat a persisted seed as the master credential it is. It is not scoped
|
|
4385
|
+
* and cannot be revoked server-side the way a session token can — rotating
|
|
4386
|
+
* it means moving the identity.
|
|
4387
|
+
*/
|
|
4388
|
+
unlockWithSeed(seedBase64: string): void;
|
|
4389
|
+
/** Poseidon commitment for an identity — the value the server stores. */
|
|
4390
|
+
private commitmentFor;
|
|
3993
4391
|
/**
|
|
3994
|
-
*
|
|
3995
|
-
*
|
|
3996
|
-
*
|
|
4392
|
+
* Derive the OPRF-gated wrap key for the password factor: `scrypt(password)`
|
|
4393
|
+
* is blinded, evaluated by the server's secret OPRF key (so it can't be
|
|
4394
|
+
* derived offline), unblinded, then HKDF'd into an AES-GCM key.
|
|
3997
4395
|
*/
|
|
3998
|
-
|
|
4396
|
+
private passwordWrapKey;
|
|
3999
4397
|
/**
|
|
4000
|
-
*
|
|
4001
|
-
*
|
|
4002
|
-
*
|
|
4003
|
-
*
|
|
4004
|
-
*
|
|
4005
|
-
*
|
|
4398
|
+
* Try to recover the master seed from the password factor.
|
|
4399
|
+
*
|
|
4400
|
+
* Returns `null` only when the vault read SUCCEEDS but the seed can't be
|
|
4401
|
+
* unwrapped — i.e. there's no real factor (a pre-vault/legacy account, whose
|
|
4402
|
+
* read returns a decoy that won't unwrap) or the password is wrong. The caller
|
|
4403
|
+
* then legitimately falls back to the legacy password-derived identity.
|
|
4404
|
+
*
|
|
4405
|
+
* Throws {@link VaultUnavailableError} when the vault itself can't be reached
|
|
4406
|
+
* (network / 5xx / rate-limit) — so a *transient* failure is NOT silently
|
|
4407
|
+
* turned into a legacy fallback (which would surface as "commitment mismatch").
|
|
4006
4408
|
*/
|
|
4007
|
-
|
|
4008
|
-
/**
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4409
|
+
private tryUnlockSeed;
|
|
4410
|
+
/**
|
|
4411
|
+
* Enroll/replace the password factor for `username` — wraps `seed` under the
|
|
4412
|
+
* OPRF-gated key and stores it (needs a session `token`).
|
|
4413
|
+
*
|
|
4414
|
+
* Retries: this is the step that persists the (otherwise in-memory-only)
|
|
4415
|
+
* master seed. If it fails after a fresh registration the account would be
|
|
4416
|
+
* unrecoverable, so we retry a few times before surfacing the error.
|
|
4417
|
+
*/
|
|
4418
|
+
private enrollPasswordFactor;
|
|
4419
|
+
}
|
|
4420
|
+
/** `client.auth` — the auth namespace. Strategies hang off here. */
|
|
4421
|
+
declare class AuthNamespace {
|
|
4422
|
+
readonly zk: ZkAuth;
|
|
4423
|
+
/** Centralized hosted auth (auth.muhkoo.dev) — `client.auth.hosted.login(...)`. */
|
|
4424
|
+
readonly hosted: HostedAuth;
|
|
4425
|
+
constructor(deps: ZkAuthDeps & {
|
|
4426
|
+
authBaseUrl: string;
|
|
4427
|
+
apiBaseUrl?: string;
|
|
4428
|
+
});
|
|
4429
|
+
/** Convenience pass-through: the currently signed-in user, or `null`. */
|
|
4430
|
+
get user(): AuthUser | null;
|
|
4015
4431
|
}
|
|
4016
4432
|
|
|
4017
4433
|
/**
|
|
@@ -6324,6 +6740,375 @@ declare class SpaceNamespace {
|
|
|
6324
6740
|
private myId;
|
|
6325
6741
|
}
|
|
6326
6742
|
|
|
6743
|
+
/**
|
|
6744
|
+
* `client.shares` — shared folders. A share is a Space the server keeps private, with a storage limit its owner pays
|
|
6745
|
+
* for, a file store whose uploaders are stamped server-side, and (for a public share) a password that admits
|
|
6746
|
+
* whoever knows it. The app's keeper holds each share's group key, so shares are not end-to-end encrypted.
|
|
6747
|
+
*
|
|
6748
|
+
* const share = await client.shares.create({ kind: "public", name: "Wedding", limitBytes: 20e9, password });
|
|
6749
|
+
* const { share, recovery } = await client.shares.joinWithPassword(spaceId, { password, name: "Gus" });
|
|
6750
|
+
*
|
|
6751
|
+
* Every member, a public share's guests included, is an ordinary Muhkoo account. Someone who opens a public share
|
|
6752
|
+
* signed out gets one quietly: a generated username and a random password they never see, a device login kept on
|
|
6753
|
+
* this device, and a recovery code ({@link GuestRecovery}) that signs them in elsewhere.
|
|
6754
|
+
*
|
|
6755
|
+
* Wire contract: the accelerator's `docs/superpowers/plans/2026-11-06-shared-folders-server-contract.md`. In short:
|
|
6756
|
+
* a share Space is created the way a public Space is (no membership-log genesis), `/metadata` first, the app keeper
|
|
6757
|
+
* seeded, then `POST /api/shares`; a rotation (new password, removed member) is a new Space adopted with
|
|
6758
|
+
* `POST /api/shares/:new/adopt`, never `/keyring/rotate`. An adopt that fails part-way is finished by repeating it
|
|
6759
|
+
* with the same new Space and the same settings, so a pending rotation is kept in the local store until it is done.
|
|
6760
|
+
*/
|
|
6761
|
+
|
|
6762
|
+
/** How many `closed.successor` links are followed before giving up (a rotation loop, or a very busy share). */
|
|
6763
|
+
declare const MAX_SHARE_SUCCESSOR_HOPS = 16;
|
|
6764
|
+
/** The default label of the device login a quietly-created guest account keeps on this device (`deviceLabel` sets another). */
|
|
6765
|
+
declare const SHARE_GUEST_DEVICE_LABEL = "Shared folder guest";
|
|
6766
|
+
/** What signs the same guest in on another device. Show it until the app calls `shares.acknowledgeRecovery()`. */
|
|
6767
|
+
interface GuestRecovery {
|
|
6768
|
+
username: string;
|
|
6769
|
+
/** The account's recovery phrase (24 words, space-separated). */
|
|
6770
|
+
phrase: string;
|
|
6771
|
+
/** `username` and `phrase` as one string to type or put in a QR code: see {@link guestRecoveryCode}. */
|
|
6772
|
+
code: string;
|
|
6773
|
+
}
|
|
6774
|
+
/** A device login for a guest account, kept on the device so the next visit signs in without asking. */
|
|
6775
|
+
interface GuestDeviceLogin {
|
|
6776
|
+
username: string;
|
|
6777
|
+
factorId: string;
|
|
6778
|
+
/** Opens the account's seed while the device factor exists: keep it as private as a session token. */
|
|
6779
|
+
deviceKey: string;
|
|
6780
|
+
}
|
|
6781
|
+
/**
|
|
6782
|
+
* Where `client.shares` keeps its per-device state: the guest device login, an unfinished guest setup, whether the
|
|
6783
|
+
* guest's recovery code is still to be shown, and unfinished rotations. String values; `set` may throw (a full or
|
|
6784
|
+
* blocked storage), `get` should answer null rather than throw.
|
|
6785
|
+
*/
|
|
6786
|
+
interface SharesLocalStore {
|
|
6787
|
+
get(key: string): Promise<string | null>;
|
|
6788
|
+
set(key: string, value: string): Promise<void>;
|
|
6789
|
+
delete(key: string): Promise<void>;
|
|
6790
|
+
}
|
|
6791
|
+
/** A store that lasts as long as the process (Node, Workers, tests). */
|
|
6792
|
+
declare function memorySharesStore(): SharesLocalStore;
|
|
6793
|
+
/**
|
|
6794
|
+
* The default store: `localStorage` under `prefix` where there is one (browsers, the same place the session token
|
|
6795
|
+
* lives), else memory. One per app: the Client keys it by the app key and the accelerator.
|
|
6796
|
+
*/
|
|
6797
|
+
declare function defaultSharesStore(prefix: string): SharesLocalStore;
|
|
6798
|
+
/** `<username>:<phrase words joined by "-">`, e.g. `g-abcdefghijkl:alpha-beta-…`. */
|
|
6799
|
+
declare function guestRecoveryCode(username: string, phrase: string): string;
|
|
6800
|
+
/** Read a {@link guestRecoveryCode}: case-insensitive, words separated by spaces or dashes. */
|
|
6801
|
+
declare function parseGuestRecoveryCode(code: string): {
|
|
6802
|
+
username: string;
|
|
6803
|
+
phrase: string;
|
|
6804
|
+
};
|
|
6805
|
+
/**
|
|
6806
|
+
* The guest recovery an error from `client.shares` carries, or null. Any error thrown after a guest account exists
|
|
6807
|
+
* carries it while it has not been acknowledged, so the app can always show the code.
|
|
6808
|
+
*/
|
|
6809
|
+
declare function guestRecoveryOf(err: unknown): GuestRecovery | null;
|
|
6810
|
+
/** The account calls `client.shares` needs for a quiet guest account: `client.auth.zk` has them all. */
|
|
6811
|
+
interface ShareGuestAuth {
|
|
6812
|
+
register(params: {
|
|
6813
|
+
username: string;
|
|
6814
|
+
password: string;
|
|
6815
|
+
}): Promise<AuthUser>;
|
|
6816
|
+
enrollDevice(label: string): Promise<{
|
|
6817
|
+
factorId: string;
|
|
6818
|
+
deviceKey: string;
|
|
6819
|
+
}>;
|
|
6820
|
+
loginWithDevice(username: string, factorId: string, deviceKey: string): Promise<AuthUser>;
|
|
6821
|
+
/** Recover the seed of the signed-in account from a device login (no new session). */
|
|
6822
|
+
unlockWithDevice(username: string, factorId: string, deviceKey: string): Promise<void>;
|
|
6823
|
+
revokeDevice(factorId: string): Promise<boolean>;
|
|
6824
|
+
/** Deterministic from the account seed: calling it again gives the same phrase. */
|
|
6825
|
+
enrollRecoveryPhrase(): Promise<string>;
|
|
6826
|
+
recoverWithPhrase(username: string, phrase: string): Promise<AuthUser>;
|
|
6827
|
+
}
|
|
6828
|
+
/** The keyring calls `client.shares` makes on a share Space (a {@link SpaceKeyring} has them). */
|
|
6829
|
+
interface ShareSpaceKeyring {
|
|
6830
|
+
admit(memberId: string, identityEcdhPub: string): Promise<void>;
|
|
6831
|
+
loadFromCache(): Promise<boolean>;
|
|
6832
|
+
hasAnyKey(): boolean;
|
|
6833
|
+
requestKey(): Promise<void>;
|
|
6834
|
+
pullKeys(): Promise<number>;
|
|
6835
|
+
}
|
|
6836
|
+
/** A share Space handle (a {@link Space} is one). */
|
|
6837
|
+
interface ShareSpaceHandle {
|
|
6838
|
+
readonly id: string;
|
|
6839
|
+
/** Absent while the session is locked. */
|
|
6840
|
+
readonly keyring?: ShareSpaceKeyring;
|
|
6841
|
+
disconnect(): void;
|
|
6842
|
+
}
|
|
6843
|
+
/** The Space calls `client.shares` makes: `client.space` has them all. */
|
|
6844
|
+
interface ShareSpaces {
|
|
6845
|
+
createSpace(opts: {
|
|
6846
|
+
historyPolicy: "static";
|
|
6847
|
+
}): Promise<ShareSpaceHandle>;
|
|
6848
|
+
get(spaceId: string): Promise<ShareSpaceHandle>;
|
|
6849
|
+
joinByInvite(spaceId: string, token: string): Promise<ShareSpaceHandle>;
|
|
6850
|
+
}
|
|
6851
|
+
interface SharesNamespaceDeps {
|
|
6852
|
+
/** The app's HTTP client (app key and the signed-in session). */
|
|
6853
|
+
http: HttpClient;
|
|
6854
|
+
/** The signed-in username, or null when no one is signed in. */
|
|
6855
|
+
me: () => string | null;
|
|
6856
|
+
/**
|
|
6857
|
+
* Whether the signed-in session holds its seed. A session restored after a reload has a token but no seed
|
|
6858
|
+
* (locked): a guest's device login unlocks it.
|
|
6859
|
+
*/
|
|
6860
|
+
unlocked: () => boolean;
|
|
6861
|
+
spaces: ShareSpaces;
|
|
6862
|
+
auth: ShareGuestAuth;
|
|
6863
|
+
store: SharesLocalStore;
|
|
6864
|
+
/** The page invite links point at; default: the current page in a browser. */
|
|
6865
|
+
inviteBase?: () => string | null;
|
|
6866
|
+
/** The wait before the n-th retry of an adopt is `n × retryDelayMs` (default 500). */
|
|
6867
|
+
retryDelayMs?: number;
|
|
6868
|
+
/** A pre-compiled Reed-Solomon module, for runtimes without the bundled loader (Node tests, Workers). */
|
|
6869
|
+
rsWasmModule?: WebAssembly.Module;
|
|
6870
|
+
}
|
|
6871
|
+
/** {@link SharesNamespace.shareFolder}'s settings for the new share (ignored when an earlier run made it already). */
|
|
6872
|
+
interface ShareFolderOptions {
|
|
6873
|
+
kind: ShareKind;
|
|
6874
|
+
/** Storage cap in bytes, or null for none. A folder bigger than this is refused before anything changes. */
|
|
6875
|
+
limitBytes: number | null;
|
|
6876
|
+
editPolicy?: EditPolicy;
|
|
6877
|
+
/** Required for a public share, refused for a private one. */
|
|
6878
|
+
password?: string;
|
|
6879
|
+
/** Default: the folder's name. */
|
|
6880
|
+
name?: string;
|
|
6881
|
+
}
|
|
6882
|
+
interface CreateShareOptions {
|
|
6883
|
+
kind: ShareKind;
|
|
6884
|
+
name: string;
|
|
6885
|
+
/** Storage cap in bytes, or null for none. */
|
|
6886
|
+
limitBytes: number | null;
|
|
6887
|
+
/** Default `"own"`: members change only their own files (the owner can always change anything). */
|
|
6888
|
+
editPolicy?: EditPolicy;
|
|
6889
|
+
/** Required for a public share, refused for a private one. Never sent: only a salted verifier is. */
|
|
6890
|
+
password?: string;
|
|
6891
|
+
}
|
|
6892
|
+
declare class SharesNamespace {
|
|
6893
|
+
private readonly deps;
|
|
6894
|
+
/** The `/api/shares` wire client, for calls this namespace does not wrap. */
|
|
6895
|
+
readonly api: SharesClient;
|
|
6896
|
+
/** The recovery phrase as last derived, so it is not re-derived on every call. */
|
|
6897
|
+
private recoveryCache;
|
|
6898
|
+
constructor(deps: SharesNamespaceDeps);
|
|
6899
|
+
/**
|
|
6900
|
+
* Make a share. The Space is created as a public Space would be (no membership-log genesis: the server refuses a
|
|
6901
|
+
* log-enabled Space), the app keeper is given its group key so members can join with the owner offline, then
|
|
6902
|
+
* `POST /api/shares` makes it a share (and private, server-side). A public share sends a salted verifier, never
|
|
6903
|
+
* the password.
|
|
6904
|
+
*/
|
|
6905
|
+
create(opts: CreateShareOptions): Promise<Share>;
|
|
6906
|
+
/**
|
|
6907
|
+
* Share a folder of the user's own (`client.vfs`): its files move into a new share, without uploading a byte,
|
|
6908
|
+
* and the folder becomes a link to the share, so the user's tree looks the same. Returns the share.
|
|
6909
|
+
*
|
|
6910
|
+
* 1. The folder's size is checked against `limitBytes` first: over it, {@link ShareFullError} and nothing
|
|
6911
|
+
* has changed.
|
|
6912
|
+
* 2. The share is made (named after the folder unless `name` is given) and the folder is marked as going
|
|
6913
|
+
* to it, so a run that stops part-way resumes into the same share.
|
|
6914
|
+
* 3. Each file's existing manifest is posted to the share at its path inside the folder.
|
|
6915
|
+
* 4. Only then is the folder replaced by the link, and only after that is each file's personal reference let
|
|
6916
|
+
* go of. Until then the owner is billed for both copies. Earlier versions of the files are not carried
|
|
6917
|
+
* into the share; they are let go of here too.
|
|
6918
|
+
*
|
|
6919
|
+
* Nothing in the folder is removed, and nothing let go of, before step 4; an interrupted run (a closed tab, a
|
|
6920
|
+
* network failure) is finished by calling `shareFolder` again on the same path: it reuses the share (following
|
|
6921
|
+
* it if it was rotated) and skips files already in it. The options are then ignored. A file saved into the
|
|
6922
|
+
* folder while it is being shared is moved too. A file (or empty folder) moved out of the folder or deleted
|
|
6923
|
+
* from it meanwhile - during the run, or between an interrupted run and the one that finishes it - is taken
|
|
6924
|
+
* back out of the share before the folder becomes a link, so the share never holds what the folder no longer
|
|
6925
|
+
* does; a file moved out keeps its personal copy. Only records this flow put in the share are taken back
|
|
6926
|
+
* (their ids are kept on this device, under the share, until the folder is a link): a file another member
|
|
6927
|
+
* uploaded meanwhile is never touched. That list is kept per device: a run finished on another device (or after
|
|
6928
|
+
* this device's storage was cleared) cannot take back what the stopped run posted. The take-back runs before
|
|
6929
|
+
* anything is posted, so what it frees counts toward the share's limit. If the run stopped after the link was in place, calling it again (or
|
|
6930
|
+
* opening the share) lets go of what was left.
|
|
6931
|
+
*
|
|
6932
|
+
* Refused with `VfsConflictError` for what is not a folder of the user's own, `/` and `/Home`, a folder that
|
|
6933
|
+
* holds a link (a share cannot hold another) or an entry this SDK version cannot read.
|
|
6934
|
+
*/
|
|
6935
|
+
shareFolder(path: string, opts: ShareFolderOptions): Promise<Share>;
|
|
6936
|
+
/** The shares the signed-in user owns or belongs to, for this app. */
|
|
6937
|
+
list(): Promise<ShareSummary[]>;
|
|
6938
|
+
/**
|
|
6939
|
+
* Open a share as the signed-in user, following `closed.successor` to the current Space, and make sure this
|
|
6940
|
+
* member has the group key (a join request the keeper answers). When the share moved to a Space this user is
|
|
6941
|
+
* not a member of (a public share's password changed), throws {@link ShareClosedError} with that Space as
|
|
6942
|
+
* `successor`: ask for the new password and call {@link joinWithPassword}.
|
|
6943
|
+
*
|
|
6944
|
+
* A guest's recovery code still to be shown is not returned here: read {@link pendingRecovery}.
|
|
6945
|
+
*/
|
|
6946
|
+
open(spaceId: string): Promise<Share>;
|
|
6947
|
+
/**
|
|
6948
|
+
* Join a public share with its password. If no one is signed in, the device login kept from an earlier visit
|
|
6949
|
+
* signs in; failing that, a guest account is made quietly. `recovery` is the guest's recovery code while the app
|
|
6950
|
+
* has not called {@link acknowledgeRecovery}: show it, then acknowledge. Any error thrown once the account
|
|
6951
|
+
* exists carries it too ({@link guestRecoveryOf}).
|
|
6952
|
+
*
|
|
6953
|
+
* Follows `closed.successor`, so an old link still reaches the current share. Throws {@link SharePasswordError}
|
|
6954
|
+
* on a wrong password, {@link SharePasswordRateError} after too many, {@link ShareMemberLimitError} when full.
|
|
6955
|
+
*/
|
|
6956
|
+
joinWithPassword(spaceId: string, opts: {
|
|
6957
|
+
password: string;
|
|
6958
|
+
name: string;
|
|
6959
|
+
deviceLabel?: string;
|
|
6960
|
+
}): Promise<{
|
|
6961
|
+
share: Share;
|
|
6962
|
+
recovery: GuestRecovery | null;
|
|
6963
|
+
}>;
|
|
6964
|
+
/**
|
|
6965
|
+
* The signed-in guest's recovery code if the app has not yet acknowledged showing it, else null. Survives a
|
|
6966
|
+
* reload: the phrase is derived again from the account (never stored), so it needs the session unlocked.
|
|
6967
|
+
*/
|
|
6968
|
+
pendingRecovery(): Promise<GuestRecovery | null>;
|
|
6969
|
+
/** The guest has saved their recovery code: stop returning it. */
|
|
6970
|
+
acknowledgeRecovery(): Promise<void>;
|
|
6971
|
+
/**
|
|
6972
|
+
* Sign a guest in on this device from their recovery code ({@link guestRecoveryCode}), and keep a device login
|
|
6973
|
+
* so the next visit signs in by itself. If another guest's login is kept on this device, throws
|
|
6974
|
+
* {@link GuestLoginConflictError} unless `replace: true`; replacing revokes that login's device factor where it
|
|
6975
|
+
* can.
|
|
6976
|
+
*/
|
|
6977
|
+
restoreGuest(code: string, opts?: {
|
|
6978
|
+
replace?: boolean;
|
|
6979
|
+
deviceLabel?: string;
|
|
6980
|
+
}): Promise<AuthUser>;
|
|
6981
|
+
/** Set the storage cap (bytes, or null for none). Owner only. */
|
|
6982
|
+
setLimit(spaceId: string, limitBytes: number | null): Promise<ShareInfo>;
|
|
6983
|
+
/** Who may change a file in a private share: `"own"` (uploader and owner) or `"any"` member. Owner only. */
|
|
6984
|
+
setEditPolicy(spaceId: string, policy: EditPolicy): Promise<ShareInfo>;
|
|
6985
|
+
/** Invite an account by username (owner only). They join by opening the share ({@link open}). */
|
|
6986
|
+
invite(spaceId: string, username: string): Promise<void>;
|
|
6987
|
+
/**
|
|
6988
|
+
* Mint an invite link (owner only): `<base>#/join/<spaceId>/<token>`, where `base` is `opts.baseUrl` or the
|
|
6989
|
+
* current page. The URL is also what an in-person invite's QR code holds. Whoever opens it signs in and calls
|
|
6990
|
+
* {@link joinWithInvite}.
|
|
6991
|
+
*/
|
|
6992
|
+
inviteLink(spaceId: string, opts?: {
|
|
6993
|
+
baseUrl?: string;
|
|
6994
|
+
}): Promise<{
|
|
6995
|
+
url: string;
|
|
6996
|
+
token: string;
|
|
6997
|
+
}>;
|
|
6998
|
+
/** Join a private share from an invite link ({@link inviteLink}) as the signed-in user. */
|
|
6999
|
+
joinWithInvite(url: string): Promise<Share>;
|
|
7000
|
+
/**
|
|
7001
|
+
* Change a public share's password. The share moves to a new Space (its files and settings come along; nothing
|
|
7002
|
+
* is uploaded again) and only the owner is carried: everyone else is admitted again with the new password, as
|
|
7003
|
+
* the same account, keeping their files and name. Returns the new share.
|
|
7004
|
+
*
|
|
7005
|
+
* Throws {@link RotationIncompleteError} if the move did not finish; calling this again (or
|
|
7006
|
+
* {@link resumeRotation}) finishes it into the same Space.
|
|
7007
|
+
*/
|
|
7008
|
+
changePassword(spaceId: string, password: string): Promise<Share>;
|
|
7009
|
+
/**
|
|
7010
|
+
* Remove a member for good: the share moves to a new Space without them (nothing is uploaded again). On a
|
|
7011
|
+
* public share pass a new `password` too, or they can be admitted again with the old one. Returns the new share.
|
|
7012
|
+
* An unfinished move is handled as in {@link changePassword}.
|
|
7013
|
+
*/
|
|
7014
|
+
removeMember(spaceId: string, username: string, opts?: {
|
|
7015
|
+
password?: string;
|
|
7016
|
+
}): Promise<Share>;
|
|
7017
|
+
/**
|
|
7018
|
+
* Finish a rotation of this share that an earlier call (on this device, perhaps before a reload) left unfinished.
|
|
7019
|
+
* Returns the new share, or null when none is pending. Throws {@link RotationIncompleteError} if it still fails.
|
|
7020
|
+
*/
|
|
7021
|
+
resumeRotation(spaceId: string): Promise<Share | null>;
|
|
7022
|
+
/**
|
|
7023
|
+
* Forget this share's unfinished rotation without finishing it. Only for a rotation you know can never complete
|
|
7024
|
+
* (its new Space is gone or refused): files the server had not yet copied stay in the closed original Space, and
|
|
7025
|
+
* the next rotation starts from wherever the share now points. Returns whether one was pending.
|
|
7026
|
+
*/
|
|
7027
|
+
abandonRotation(spaceId: string): Promise<boolean>;
|
|
7028
|
+
private rotate;
|
|
7029
|
+
/** Send the adopt (with retries on network errors and 5xx); forget the rotation once done or dead. */
|
|
7030
|
+
private finishRotation;
|
|
7031
|
+
/** The unfinished rotation `spaceId` belongs to: as its `from`, its new Space, or a Space before its `from`. */
|
|
7032
|
+
private pendingRotationFor;
|
|
7033
|
+
private loadRotations;
|
|
7034
|
+
private saveRotation;
|
|
7035
|
+
private dropRotation;
|
|
7036
|
+
/**
|
|
7037
|
+
* The share `plan`'s folder is going to: the one an earlier run marked it with (its successor if it was
|
|
7038
|
+
* rotated), else a new one, made only once the folder is known to fit and then marked on the folder.
|
|
7039
|
+
*/
|
|
7040
|
+
private shareForFolder;
|
|
7041
|
+
/**
|
|
7042
|
+
* Post every file of `plan` to `share`, and its empty folders. Nothing of the user's is let go of here. Each
|
|
7043
|
+
* record's id is noted in `posted` before it is posted. Returns the ids of the records that hold `plan`'s files.
|
|
7044
|
+
*/
|
|
7045
|
+
private moveIntoShare;
|
|
7046
|
+
/**
|
|
7047
|
+
* Delete from `share` each record this flow posted (`posted`) that `plan` no longer has: a file record
|
|
7048
|
+
* `keepFile` does not keep (deleted or moved out of the folder, or left at an old path), an empty-folder record
|
|
7049
|
+
* whose path is no longer a folder in `plan`. Only the caller's own uploads, and only ids in `posted`, are touched.
|
|
7050
|
+
*/
|
|
7051
|
+
private takeBackRemoved;
|
|
7052
|
+
private savePending;
|
|
7053
|
+
/**
|
|
7054
|
+
* Let go of the personal reference of each file a `shareFolder` into `spaceId` moved out of the tree - only
|
|
7055
|
+
* once the folder it kept is confirmed to be a link to `spaceId` (until then the folder's entries still name
|
|
7056
|
+
* that content, and their references keep it stored). Each file once; the list shrinks as it goes, so a
|
|
7057
|
+
* repeat never releases one twice. A failed release stays listed for next time: a leak (billed twice) is the
|
|
7058
|
+
* worst case, never a loss. True when there was a list for `spaceId` and the swap was confirmed. `known`: the
|
|
7059
|
+
* list as this run has it (the stored copy may not have been saved).
|
|
7060
|
+
*/
|
|
7061
|
+
private drainPending;
|
|
7062
|
+
/**
|
|
7063
|
+
* Create a share Space and seed its keeper; returns its id. The keeper's key is read first, so an app without a
|
|
7064
|
+
* keeper leaves no Space behind. Created with the default (public) visibility: a private Space gets a
|
|
7065
|
+
* membership-log genesis, which a share refuses. The socket the creation opens is closed again: a `Share` works
|
|
7066
|
+
* over HTTP.
|
|
7067
|
+
*/
|
|
7068
|
+
private newSeededSpace;
|
|
7069
|
+
/** The app keeper's ECDH public key, or null when the app has none (404). */
|
|
7070
|
+
private keeperPubkey;
|
|
7071
|
+
/** The share's current Space: `spaceId` or where its `closed.successor` chain ends. */
|
|
7072
|
+
private current;
|
|
7073
|
+
/** A public share's current Space and its pre-admission info (salt, iterations), from `GET /public`. */
|
|
7074
|
+
private currentPublic;
|
|
7075
|
+
/**
|
|
7076
|
+
* Make sure the signed-in member holds the share's group key: a key from this device's cache, else a join
|
|
7077
|
+
* request (the keeper wraps the key for a member as it lands) and a few pulls. A locked session (no identity)
|
|
7078
|
+
* skips this: the share's files do not need the group key. A key that has not arrived yet is not an error.
|
|
7079
|
+
*/
|
|
7080
|
+
private joinKeys;
|
|
7081
|
+
/** Signed in already; else this device's guest login; else a new guest account. Finishes a half-done setup. */
|
|
7082
|
+
private ensureSignedIn;
|
|
7083
|
+
private createGuestAccount;
|
|
7084
|
+
/**
|
|
7085
|
+
* Finish the steps of a guest account's setup that are not done: the recovery phrase first (so it can always be
|
|
7086
|
+
* shown), then the device login. Each is tried twice. An error carries the recovery when the phrase is known.
|
|
7087
|
+
*/
|
|
7088
|
+
private finishGuestSetup;
|
|
7089
|
+
/**
|
|
7090
|
+
* Best-effort revoke of a replaced guest login's device factor. Revoking needs that account's session, so this
|
|
7091
|
+
* signs in as it briefly and then back in as `current` (the guest just restored), whose login is fresh.
|
|
7092
|
+
*/
|
|
7093
|
+
private revokeReplacedLogin;
|
|
7094
|
+
/** Delete `key` if its JSON value names `username`. */
|
|
7095
|
+
private deleteIfFor;
|
|
7096
|
+
/**
|
|
7097
|
+
* A session restored without its seed (after a reload) that belongs to this device's guest login: unlock it
|
|
7098
|
+
* with the device login, so the setup can be finished and the recovery phrase derived. A revoked login is
|
|
7099
|
+
* forgotten; any other failure is warned and leaves the session locked.
|
|
7100
|
+
*/
|
|
7101
|
+
private unlockSavedGuest;
|
|
7102
|
+
/** `err` with the signed-in guest's unacknowledged recovery attached as `recovery` (see {@link guestRecoveryOf}). */
|
|
7103
|
+
private withRecovery;
|
|
7104
|
+
private readJson;
|
|
7105
|
+
/** Store `value`; a storage failure is reported (warned) and answered with false, not thrown. */
|
|
7106
|
+
private trySave;
|
|
7107
|
+
private keyring;
|
|
7108
|
+
private shareFor;
|
|
7109
|
+
private requireMe;
|
|
7110
|
+
}
|
|
7111
|
+
|
|
6327
7112
|
/**
|
|
6328
7113
|
* `client.agents` — manage an app's **Programmable Agents** (server-side
|
|
6329
7114
|
* "virtual users" backed by Workers AI).
|
|
@@ -6372,6 +7157,8 @@ interface AgentToolsConfig {
|
|
|
6372
7157
|
functions: string[];
|
|
6373
7158
|
/** Whether the agent may resolve the app's PUBLIC channels. */
|
|
6374
7159
|
channels: boolean;
|
|
7160
|
+
/** Allowlisted collection names the agent may search with its `search_collection` tool (text-mode collections only, at most 20). */
|
|
7161
|
+
collections?: string[];
|
|
6375
7162
|
/** Max tool-call rounds per reply (1..6). */
|
|
6376
7163
|
maxIterations: number;
|
|
6377
7164
|
}
|
|
@@ -6775,6 +7562,233 @@ declare class AppNamespace {
|
|
|
6775
7562
|
access(): Promise<AppAccess>;
|
|
6776
7563
|
}
|
|
6777
7564
|
|
|
7565
|
+
/**
|
|
7566
|
+
* `client.vectors` — vector search over the app's collections. A developer
|
|
7567
|
+
* defines a collection (text or vectors mode, filterable fields, access) in the
|
|
7568
|
+
* Muhkoo portal or CLI; this namespace reads and writes its entries:
|
|
7569
|
+
*
|
|
7570
|
+
* const docs = client.vectors.collection('docs');
|
|
7571
|
+
* const { mutationId } = await docs.upsert([
|
|
7572
|
+
* { id: 'doc-1', text: 'How to reset your password…', data: { category: 'faq' } },
|
|
7573
|
+
* ]);
|
|
7574
|
+
* const state = await docs.status(mutationId); // 'pending' | 'done' | 'unknown'
|
|
7575
|
+
* const matches = await docs.query({ text: 'forgot password', topK: 5, filter: { category: 'faq' } });
|
|
7576
|
+
* const [entry] = await docs.get(['doc-1']);
|
|
7577
|
+
* await docs.delete(['doc-1']);
|
|
7578
|
+
*
|
|
7579
|
+
* Writes are asynchronous: upsert and delete return a `mutationId` at once, and
|
|
7580
|
+
* entries usually become searchable within one to two minutes. `get` returns
|
|
7581
|
+
* only entries whose writes have finished, never ones still pending.
|
|
7582
|
+
*
|
|
7583
|
+
* Entries are server-readable: Muhkoo stores the text, vectors and data you send
|
|
7584
|
+
* so it can embed and search them. Don't put anything in a collection that the
|
|
7585
|
+
* platform must not see.
|
|
7586
|
+
*
|
|
7587
|
+
* Authorization is the app key ({@link HttpClient} stamps it on every request);
|
|
7588
|
+
* the app and environment come from the key. Server errors (`{ error, code }`)
|
|
7589
|
+
* reach callers as {@link HttpError}; the SDK does no validation of its own.
|
|
7590
|
+
*/
|
|
7591
|
+
|
|
7592
|
+
/** A ready notice: the entries of one upsert call are now searchable. */
|
|
7593
|
+
interface VectorReadyEvent {
|
|
7594
|
+
collection: string;
|
|
7595
|
+
ids: string[];
|
|
7596
|
+
mutationId: string;
|
|
7597
|
+
}
|
|
7598
|
+
/**
|
|
7599
|
+
* A wait for a write ran out of time. The write itself was accepted; check
|
|
7600
|
+
* {@link VectorCollection.status} later with `mutationId`.
|
|
7601
|
+
*/
|
|
7602
|
+
declare class VectorWaitTimeoutError extends Error {
|
|
7603
|
+
readonly mutationId: string;
|
|
7604
|
+
constructor(mutationId: string, timeoutMs: number);
|
|
7605
|
+
}
|
|
7606
|
+
type WaitOptions = {
|
|
7607
|
+
space?: Space;
|
|
7608
|
+
timeoutMs?: number;
|
|
7609
|
+
};
|
|
7610
|
+
type VectorAudience = "everyone" | "writer";
|
|
7611
|
+
type VectorNotify = false | {
|
|
7612
|
+
space?: string;
|
|
7613
|
+
audience?: VectorAudience;
|
|
7614
|
+
};
|
|
7615
|
+
interface VectorEntryInput {
|
|
7616
|
+
id: string;
|
|
7617
|
+
text?: string;
|
|
7618
|
+
vector?: number[];
|
|
7619
|
+
data?: Record<string, unknown>;
|
|
7620
|
+
storeText?: boolean;
|
|
7621
|
+
}
|
|
7622
|
+
interface VectorUpsertOptions {
|
|
7623
|
+
notify?: VectorNotify;
|
|
7624
|
+
}
|
|
7625
|
+
interface VectorWriteResult {
|
|
7626
|
+
mutationId: string;
|
|
7627
|
+
count: number;
|
|
7628
|
+
}
|
|
7629
|
+
interface VectorQueryInput {
|
|
7630
|
+
text?: string;
|
|
7631
|
+
vector?: number[];
|
|
7632
|
+
topK?: number;
|
|
7633
|
+
filter?: Record<string, unknown>;
|
|
7634
|
+
includeData?: boolean;
|
|
7635
|
+
includeText?: boolean;
|
|
7636
|
+
}
|
|
7637
|
+
interface VectorMatch {
|
|
7638
|
+
id: string;
|
|
7639
|
+
score: number;
|
|
7640
|
+
data?: Record<string, unknown>;
|
|
7641
|
+
text?: string;
|
|
7642
|
+
}
|
|
7643
|
+
interface VectorEntry {
|
|
7644
|
+
id: string;
|
|
7645
|
+
data: Record<string, unknown>;
|
|
7646
|
+
text?: string;
|
|
7647
|
+
vector?: number[];
|
|
7648
|
+
}
|
|
7649
|
+
type VectorWriteState = "pending" | "done" | "unknown";
|
|
7650
|
+
interface VectorsNamespaceDeps {
|
|
7651
|
+
http: HttpClient;
|
|
7652
|
+
}
|
|
7653
|
+
/** A handle on one collection. Cheap to make; holds no state beyond its name. */
|
|
7654
|
+
declare class VectorCollection {
|
|
7655
|
+
private readonly http;
|
|
7656
|
+
readonly name: string;
|
|
7657
|
+
private readonly base;
|
|
7658
|
+
constructor(http: HttpClient, name: string);
|
|
7659
|
+
/** Add or replace entries. Returns once accepted; see {@link status}. */
|
|
7660
|
+
upsert(entries: VectorEntryInput[], opts?: VectorUpsertOptions): Promise<VectorWriteResult>;
|
|
7661
|
+
/** Nearest entries to a text or a vector. */
|
|
7662
|
+
query(input: VectorQueryInput): Promise<VectorMatch[]>;
|
|
7663
|
+
/** Entries by id. Writes still pending are not returned. */
|
|
7664
|
+
get(ids: string[], opts?: {
|
|
7665
|
+
includeVector?: boolean;
|
|
7666
|
+
}): Promise<VectorEntry[]>;
|
|
7667
|
+
/** Remove entries by id. Asynchronous, like {@link upsert}. */
|
|
7668
|
+
delete(ids: string[]): Promise<VectorWriteResult>;
|
|
7669
|
+
/** The state of a write: `pending`, `done`, or `unknown` (never seen or expired). */
|
|
7670
|
+
status(mutationId: string): Promise<VectorWriteState>;
|
|
7671
|
+
/**
|
|
7672
|
+
* Listen on an open Space for this collection's ready notices. Only notices
|
|
7673
|
+
* the platform sent (sender `__muhkoo__`) reach `handler`; a member who
|
|
7674
|
+
* publishes the same subject is ignored. Needs an unlocked session, since a
|
|
7675
|
+
* Space without its keys emits no ephemeral events. Returns the unsubscribe.
|
|
7676
|
+
*/
|
|
7677
|
+
onReady(space: Space, handler: (e: VectorReadyEvent) => void): () => void;
|
|
7678
|
+
/**
|
|
7679
|
+
* Resolve once a write is searchable: on its ready notice (with `space`) or
|
|
7680
|
+
* when {@link status} answers `done`. Status is polled underneath either way,
|
|
7681
|
+
* because notices are best effort.
|
|
7682
|
+
*
|
|
7683
|
+
* The notice only arrives if `space` is a registered notice Space for the
|
|
7684
|
+
* environment (see {@link VectorsNamespace.setNotices}) and the write named
|
|
7685
|
+
* it in `notify.space` or it is the environment's `defaultSpace`. Any other
|
|
7686
|
+
* Space never receives the notice, and the wait falls back to polling,
|
|
7687
|
+
* usually finishing within a minute or two.
|
|
7688
|
+
*
|
|
7689
|
+
* Rejects with an `Error` ("Unknown mutation <id>") if status answers
|
|
7690
|
+
* `unknown`, and with {@link VectorWaitTimeoutError} after `timeoutMs`
|
|
7691
|
+
* (default 300,000 ms).
|
|
7692
|
+
*/
|
|
7693
|
+
waitFor(mutationId: string, opts?: WaitOptions): Promise<void>;
|
|
7694
|
+
/**
|
|
7695
|
+
* {@link upsert}, then {@link waitFor} its mutation. With `space`, listens
|
|
7696
|
+
* before sending, so a notice that beats the HTTP response still counts.
|
|
7697
|
+
* The notice reaches `space` only if it is a registered notice Space named
|
|
7698
|
+
* in `notify.space` or set as the environment's `defaultSpace`; naming an
|
|
7699
|
+
* unregistered Space fails the upsert with a 400
|
|
7700
|
+
* `notice_space_not_registered`. Otherwise the wait completes by polling.
|
|
7701
|
+
* An upsert error is rethrown at once.
|
|
7702
|
+
*/
|
|
7703
|
+
upsertAndWait(entries: VectorEntryInput[], opts?: VectorUpsertOptions & WaitOptions): Promise<VectorWriteResult>;
|
|
7704
|
+
private wait;
|
|
7705
|
+
}
|
|
7706
|
+
interface VectorFieldDefinition {
|
|
7707
|
+
name: string;
|
|
7708
|
+
type: "string" | "number" | "boolean";
|
|
7709
|
+
}
|
|
7710
|
+
type VectorCollectionDefinition = {
|
|
7711
|
+
mode: "text";
|
|
7712
|
+
model?: string;
|
|
7713
|
+
metric?: "cosine" | "euclidean" | "dot-product";
|
|
7714
|
+
fields?: VectorFieldDefinition[];
|
|
7715
|
+
access?: "app" | "backend";
|
|
7716
|
+
} | {
|
|
7717
|
+
mode: "vectors";
|
|
7718
|
+
dimensions: number;
|
|
7719
|
+
metric?: "cosine" | "euclidean" | "dot-product";
|
|
7720
|
+
fields?: VectorFieldDefinition[];
|
|
7721
|
+
access?: "app" | "backend";
|
|
7722
|
+
};
|
|
7723
|
+
interface VectorNotices {
|
|
7724
|
+
spaces: string[];
|
|
7725
|
+
defaultSpace: string | null;
|
|
7726
|
+
}
|
|
7727
|
+
interface VectorEnvInfo {
|
|
7728
|
+
status: "creating" | "ready" | "failed" | "dropping";
|
|
7729
|
+
entries: number | null;
|
|
7730
|
+
notices: VectorNotices;
|
|
7731
|
+
error: string | null;
|
|
7732
|
+
}
|
|
7733
|
+
interface VectorCollectionInfo {
|
|
7734
|
+
name: string;
|
|
7735
|
+
mode: "text" | "vectors";
|
|
7736
|
+
model: string | null;
|
|
7737
|
+
dimensions: number;
|
|
7738
|
+
metric: string;
|
|
7739
|
+
fields: VectorFieldDefinition[];
|
|
7740
|
+
access: "app" | "backend";
|
|
7741
|
+
createdAt: number;
|
|
7742
|
+
status: "creating" | "ready" | "failed" | "dropping";
|
|
7743
|
+
envs: {
|
|
7744
|
+
live: VectorEnvInfo;
|
|
7745
|
+
test: VectorEnvInfo;
|
|
7746
|
+
};
|
|
7747
|
+
}
|
|
7748
|
+
/** A collection's creation failed; `info.envs.*.error` says why. */
|
|
7749
|
+
declare class VectorCollectionFailedError extends Error {
|
|
7750
|
+
readonly info: VectorCollectionInfo;
|
|
7751
|
+
constructor(info: VectorCollectionInfo);
|
|
7752
|
+
}
|
|
7753
|
+
declare class VectorsNamespace {
|
|
7754
|
+
private readonly deps;
|
|
7755
|
+
constructor(deps: VectorsNamespaceDeps);
|
|
7756
|
+
/** A handle on the named collection, made fresh on each call. */
|
|
7757
|
+
collection(name: string): VectorCollection;
|
|
7758
|
+
/** The app's collections, sorted by name. */
|
|
7759
|
+
listCollections(appId: string): Promise<VectorCollectionInfo[]>;
|
|
7760
|
+
/** One collection. A missing or badly named one is 404 `collection_not_found`. */
|
|
7761
|
+
getCollection(appId: string, name: string): Promise<VectorCollectionInfo>;
|
|
7762
|
+
/**
|
|
7763
|
+
* Create a collection. Asynchronous: it answers with status `creating`; use
|
|
7764
|
+
* {@link waitForCollection} to wait for `ready`. Repeating it with the same
|
|
7765
|
+
* definition returns the existing collection; a different definition is
|
|
7766
|
+
* 409 `collection_exists`. Definitions never change: drop and recreate.
|
|
7767
|
+
*/
|
|
7768
|
+
createCollection(appId: string, name: string, definition: VectorCollectionDefinition): Promise<VectorCollectionInfo>;
|
|
7769
|
+
/**
|
|
7770
|
+
* Drop a collection and its entries in both environments. Asynchronous; the
|
|
7771
|
+
* collection shows status `dropping` until it is gone. Safe to repeat: a 503
|
|
7772
|
+
* `vectors_unavailable` means the drop couldn't start, and calling again is
|
|
7773
|
+
* the remedy.
|
|
7774
|
+
*/
|
|
7775
|
+
dropCollection(appId: string, name: string): Promise<void>;
|
|
7776
|
+
/** Set which Spaces receive ready notices for one environment. */
|
|
7777
|
+
setNotices(appId: string, name: string, env: "live" | "test", notices: VectorNotices): Promise<VectorNotices & {
|
|
7778
|
+
env: "live" | "test";
|
|
7779
|
+
}>;
|
|
7780
|
+
/**
|
|
7781
|
+
* Poll {@link getCollection} every 2 s until status is `ready`. Rejects with
|
|
7782
|
+
* {@link VectorCollectionFailedError} on `failed`, and with
|
|
7783
|
+
* `Error("Timed out waiting for collection <name>")` after `timeoutMs`
|
|
7784
|
+
* (default 600,000 ms: creation waits for filter fields to settle).
|
|
7785
|
+
*/
|
|
7786
|
+
waitForCollection(appId: string, name: string, opts?: {
|
|
7787
|
+
timeoutMs?: number;
|
|
7788
|
+
}): Promise<VectorCollectionInfo>;
|
|
7789
|
+
private ownerPath;
|
|
7790
|
+
}
|
|
7791
|
+
|
|
6778
7792
|
/**
|
|
6779
7793
|
* Wire types for the VFS metadata layer.
|
|
6780
7794
|
*
|
|
@@ -6871,8 +7885,37 @@ interface DirEntry {
|
|
|
6871
7885
|
* storage cost, never a loss.
|
|
6872
7886
|
*/
|
|
6873
7887
|
moving?: true;
|
|
7888
|
+
/**
|
|
7889
|
+
* Set while `client.shares.shareFolder` is moving this folder's files into the share named here, until the
|
|
7890
|
+
* folder is replaced by a link to it. A run that stops part-way resumes into the same share. An SDK from
|
|
7891
|
+
* before shares keeps the field (entries are written back whole) and otherwise ignores it.
|
|
7892
|
+
*/
|
|
7893
|
+
sharing?: {
|
|
7894
|
+
spaceId: string;
|
|
7895
|
+
};
|
|
7896
|
+
}
|
|
7897
|
+
/**
|
|
7898
|
+
* A link: a name in the user's own tree that stands for a shared folder (a share), the way a symlink stands for
|
|
7899
|
+
* a directory. Paths below it are served by that share; the link itself holds nothing of the user's, so deleting
|
|
7900
|
+
* or moving it touches only the link.
|
|
7901
|
+
*
|
|
7902
|
+
* Added after `file` and `dir` without a new record version (`DirNode.v` stays 1): an SDK from before links
|
|
7903
|
+
* sees an entry kind it does not know, hides it, writes it back unchanged with every write of the directory, and
|
|
7904
|
+
* refuses to put anything else at its name with `mkdir`, `rename` or `copy`.
|
|
7905
|
+
*/
|
|
7906
|
+
interface LinkEntry {
|
|
7907
|
+
kind: "link";
|
|
7908
|
+
/** Stable identity, like a file's or a directory's. Never a store key: a link has no record of its own. */
|
|
7909
|
+
id: string;
|
|
7910
|
+
/** The share's Space. */
|
|
7911
|
+
target: {
|
|
7912
|
+
spaceId: string;
|
|
7913
|
+
};
|
|
7914
|
+
mtime: number;
|
|
7915
|
+
/** See `DirEntry.moving`. */
|
|
7916
|
+
moving?: true;
|
|
6874
7917
|
}
|
|
6875
|
-
type Entry = FileEntry | DirEntry;
|
|
7918
|
+
type Entry = FileEntry | DirEntry | LinkEntry;
|
|
6876
7919
|
/** One directory record, as stored (before encryption). */
|
|
6877
7920
|
interface DirNode {
|
|
6878
7921
|
v: 1;
|
|
@@ -6893,10 +7936,14 @@ interface HistoryRecord {
|
|
|
6893
7936
|
interface VfsStat {
|
|
6894
7937
|
path: string;
|
|
6895
7938
|
name: string;
|
|
6896
|
-
kind: "file" | "dir";
|
|
7939
|
+
kind: "file" | "dir" | "link";
|
|
6897
7940
|
size: number;
|
|
6898
7941
|
mtime: number;
|
|
6899
7942
|
versions: number;
|
|
7943
|
+
/** For a link: the share it stands for. */
|
|
7944
|
+
target?: {
|
|
7945
|
+
spaceId: string;
|
|
7946
|
+
};
|
|
6900
7947
|
}
|
|
6901
7948
|
/** The encrypted envelope every record is stored in. */
|
|
6902
7949
|
interface SealedRecord {
|
|
@@ -7092,6 +8139,28 @@ interface VfsCoordinator {
|
|
|
7092
8139
|
holdMoving(id: string, shared?: boolean): Promise<(() => void) | null>;
|
|
7093
8140
|
}
|
|
7094
8141
|
|
|
8142
|
+
/**
|
|
8143
|
+
* The shares mount: how the VFS serves `/Home/Shared` and paths through a link.
|
|
8144
|
+
*
|
|
8145
|
+
* A share is its own Space with its own file records, not a subtree of anyone's personal tree. So nothing here
|
|
8146
|
+
* reads or writes a directory record: every path below `/Home/Shared/<name>`, or below a link, becomes a call on
|
|
8147
|
+
* that share's `Share` (list, read, write, mkdir, delete, rename), and a share's tree comes back as `VfsStat`s.
|
|
8148
|
+
* `VfsNamespace` decides which paths come here (see `VfsNamespace.route`); this file never touches the personal
|
|
8149
|
+
* store, so nothing a share does can reach the user's own files.
|
|
8150
|
+
*
|
|
8151
|
+
* `/Home/Shared` itself is built from the server's membership records (`shares.list()`), never stored.
|
|
8152
|
+
*/
|
|
8153
|
+
|
|
8154
|
+
/** The part of a `Share` the VFS uses. `info` is read to make sure a share kept open has not been closed. */
|
|
8155
|
+
type MountedShare = Pick<Share, "spaceId" | "info" | "list" | "read" | "write" | "mkdir" | "delete" | "rename">;
|
|
8156
|
+
/** Where the shares come from: `client.shares`. */
|
|
8157
|
+
interface SharesSource {
|
|
8158
|
+
list(): Promise<ShareSummary[]>;
|
|
8159
|
+
open(spaceId: string): Promise<MountedShare>;
|
|
8160
|
+
/** The signed-in username, so that the user's own shares get the plain names. Null when unknown. */
|
|
8161
|
+
me?: () => string | null;
|
|
8162
|
+
}
|
|
8163
|
+
|
|
7095
8164
|
/**
|
|
7096
8165
|
* `client.vfs` — a real filesystem over Muhkoo primitives.
|
|
7097
8166
|
*
|
|
@@ -7195,6 +8264,13 @@ interface VfsNamespaceDeps {
|
|
|
7195
8264
|
* namespace only. See `VfsCoordinator`.
|
|
7196
8265
|
*/
|
|
7197
8266
|
coordinator?: VfsCoordinator;
|
|
8267
|
+
/**
|
|
8268
|
+
* The signed-in user's shares (`client.shares`). With it, `/Home/Shared` lists them and paths below
|
|
8269
|
+
* `/Home/Shared/<name>`, or below a link, are served by the share; `/Home` is the user's own `/Home` folder
|
|
8270
|
+
* with `Shared` added. Without it - a CLI or a test with no shares - a link is listed, moved, copied and
|
|
8271
|
+
* deleted like any entry, but nothing below it can be reached.
|
|
8272
|
+
*/
|
|
8273
|
+
shares?: SharesSource;
|
|
7198
8274
|
}
|
|
7199
8275
|
declare class VfsNamespace {
|
|
7200
8276
|
private readonly deps;
|
|
@@ -7316,6 +8392,8 @@ declare class VfsNamespace {
|
|
|
7316
8392
|
private readonly historyLimit;
|
|
7317
8393
|
private readonly maxEntries;
|
|
7318
8394
|
private readonly maxPathChars;
|
|
8395
|
+
/** `/Home/Shared` and the shares below it and below links. See `sharesMount.ts`. */
|
|
8396
|
+
private readonly mount;
|
|
7319
8397
|
constructor(deps: VfsNamespaceDeps);
|
|
7320
8398
|
/**
|
|
7321
8399
|
* The working directory relative paths resolve against.
|
|
@@ -7364,9 +8442,15 @@ declare class VfsNamespace {
|
|
|
7364
8442
|
*/
|
|
7365
8443
|
watch(handler: () => void): () => void;
|
|
7366
8444
|
exists(path: string): Promise<boolean>;
|
|
8445
|
+
private existsReal;
|
|
7367
8446
|
stat(path: string): Promise<VfsStat>;
|
|
7368
|
-
|
|
8447
|
+
private statReal;
|
|
8448
|
+
/**
|
|
8449
|
+
* Immediate children of a directory. One record fetch. A link is listed as `kind: "link"` with its
|
|
8450
|
+
* `target`; listing the link's own path lists the share it stands for.
|
|
8451
|
+
*/
|
|
7369
8452
|
list(path?: string): Promise<VfsStat[]>;
|
|
8453
|
+
private listReal;
|
|
7370
8454
|
/**
|
|
7371
8455
|
* A directory's entries in listing order: directories first, then by name.
|
|
7372
8456
|
* Shared by `list` and `walk`, so a walk's output order is exactly the order
|
|
@@ -7405,9 +8489,22 @@ declare class VfsNamespace {
|
|
|
7405
8489
|
* whole walk beside the whole commit, and a map of one beside a map of
|
|
7406
8490
|
* the other, ran a 512MB heap out of memory inside the default budgets.
|
|
7407
8491
|
* The same guards and budgets as `walk`, which is built on this.
|
|
8492
|
+
*
|
|
8493
|
+
* A link is visited as `kind: "link"` (with a null manifest) and not walked into: it is the user's entry,
|
|
8494
|
+
* while what is below it is a share's. A walk of `/Home` covers only the user's own `/Home` folder, not
|
|
8495
|
+
* `/Home/Shared`.
|
|
8496
|
+
*
|
|
8497
|
+
* Throws VfsConflictError for a path at a link, at `/Home/Shared` or inside a share: a share's files are not
|
|
8498
|
+
* content handles of the user's, so there is no manifest to hand over, and a caller that reads a null
|
|
8499
|
+
* manifest as "a directory" - version control does - would record a tree with no files in it. `walk` and
|
|
8500
|
+
* `walkEntries` do walk shares.
|
|
7408
8501
|
*/
|
|
7409
8502
|
eachEntry(path: string, visit: (stat: VfsStat, manifest: FileManifest | null) => void): Promise<void>;
|
|
8503
|
+
/** `eachEntry`, and with `intoShares` (for `walkEntries`) also a walk of a share: every file's manifest null. */
|
|
8504
|
+
private visitTree;
|
|
8505
|
+
private eachReal;
|
|
7410
8506
|
readFile(path: string): Promise<Uint8Array>;
|
|
8507
|
+
private readFileReal;
|
|
7411
8508
|
readText(path: string): Promise<string>;
|
|
7412
8509
|
/**
|
|
7413
8510
|
* A file's manifest — the handle itself, without reading the bytes.
|
|
@@ -7445,6 +8542,7 @@ declare class VfsNamespace {
|
|
|
7445
8542
|
* shards.
|
|
7446
8543
|
*/
|
|
7447
8544
|
writeManifest(path: string, manifest: FileManifest, size: number): Promise<VfsStat>;
|
|
8545
|
+
private writeManifestReal;
|
|
7448
8546
|
/**
|
|
7449
8547
|
* Create a directory. `recursive` creates missing parents and tolerates an
|
|
7450
8548
|
* existing target, matching `mkdir -p`.
|
|
@@ -7452,6 +8550,7 @@ declare class VfsNamespace {
|
|
|
7452
8550
|
mkdir(path: string, opts?: {
|
|
7453
8551
|
recursive?: boolean;
|
|
7454
8552
|
}): Promise<void>;
|
|
8553
|
+
private mkdirReal;
|
|
7455
8554
|
/**
|
|
7456
8555
|
* Refuse now what creating these directories with `mkdir -p` would refuse
|
|
7457
8556
|
* part way: one deeper than MAX_DEPTH, or a name on the way held by an
|
|
@@ -7462,6 +8561,7 @@ declare class VfsNamespace {
|
|
|
7462
8561
|
* not refused: such an operation removes those first.
|
|
7463
8562
|
*/
|
|
7464
8563
|
assertCreatable(dirs: Iterable<string>): Promise<void>;
|
|
8564
|
+
private assertCreatableReal;
|
|
7465
8565
|
/**
|
|
7466
8566
|
* Write a file, creating parent directories as needed.
|
|
7467
8567
|
*
|
|
@@ -7473,6 +8573,7 @@ declare class VfsNamespace {
|
|
|
7473
8573
|
type?: string;
|
|
7474
8574
|
onProgress?: (done: number, total: number) => void;
|
|
7475
8575
|
}): Promise<VfsStat>;
|
|
8576
|
+
private writeFileReal;
|
|
7476
8577
|
/**
|
|
7477
8578
|
* Delete a file, or a directory when `recursive`.
|
|
7478
8579
|
*
|
|
@@ -7485,6 +8586,12 @@ declare class VfsNamespace {
|
|
|
7485
8586
|
recursive?: boolean;
|
|
7486
8587
|
keepContent?: boolean;
|
|
7487
8588
|
}): Promise<void>;
|
|
8589
|
+
/**
|
|
8590
|
+
* `swap`: instead of deleting the folder, put `swap.link` in its place (see `finishSharing`). Everything else
|
|
8591
|
+
* a recursive delete does to keep a concurrent move or write from being lost is the same; what it would let
|
|
8592
|
+
* go of, or detach unread, it refuses instead.
|
|
8593
|
+
*/
|
|
8594
|
+
private deleteReal;
|
|
7488
8595
|
/**
|
|
7489
8596
|
* Move or rename. Works across directories, which is the same operation:
|
|
7490
8597
|
* detach the entry from one parent and attach it to another.
|
|
@@ -7495,6 +8602,7 @@ declare class VfsNamespace {
|
|
|
7495
8602
|
* first: what is below must still be inside MAX_DEPTH once it is moved.
|
|
7496
8603
|
*/
|
|
7497
8604
|
rename(from: string, to: string): Promise<void>;
|
|
8605
|
+
private renameReal;
|
|
7498
8606
|
/**
|
|
7499
8607
|
* Refuse to move the directory at `src` to `dst` when something in it
|
|
7500
8608
|
* would then be deeper than MAX_DEPTH from the root. Writes nothing.
|
|
@@ -7519,6 +8627,7 @@ declare class VfsNamespace {
|
|
|
7519
8627
|
* onto the other.
|
|
7520
8628
|
*/
|
|
7521
8629
|
copy(from: string, to: string): Promise<VfsStat>;
|
|
8630
|
+
private copyReal;
|
|
7522
8631
|
/**
|
|
7523
8632
|
* Paths matching a glob, relative to the whole filesystem.
|
|
7524
8633
|
*
|
|
@@ -7564,6 +8673,106 @@ declare class VfsNamespace {
|
|
|
7564
8673
|
* undoable rather than a one-way door.
|
|
7565
8674
|
*/
|
|
7566
8675
|
restore(path: string, index?: number): Promise<VfsStat>;
|
|
8676
|
+
private restoreReal;
|
|
8677
|
+
/**
|
|
8678
|
+
* Put a link to a share at `path` in the user's own files. Paths below it are then served by that share,
|
|
8679
|
+
* as paths below `/Home/Shared/<name>` are. The link holds nothing else: deleting it, moving it or copying it
|
|
8680
|
+
* touches only the link, never the share.
|
|
8681
|
+
*
|
|
8682
|
+
* Throws VfsConflictError when anything is at `path` already (including an entry this version cannot read),
|
|
8683
|
+
* and for a place a link cannot go: `/Home/Shared`, `/Home`, or inside a share.
|
|
8684
|
+
*/
|
|
8685
|
+
link(path: string, spaceId: string): Promise<void>;
|
|
8686
|
+
/** The share a link at `path` stands for. VfsConflictError when what is there is not a link. */
|
|
8687
|
+
readLink(path: string): Promise<{
|
|
8688
|
+
spaceId: string;
|
|
8689
|
+
}>;
|
|
8690
|
+
/** `readLink`, with the link entry's own id (for `client.shares.shareFolder`: see `sharingAccess.ts`). */
|
|
8691
|
+
private readLinkEntry;
|
|
8692
|
+
/**
|
|
8693
|
+
* Read a folder of the user's own for sharing: every file below it with its manifest, the empty folders, and
|
|
8694
|
+
* the share an unfinished earlier run was moving it into. Changes nothing.
|
|
8695
|
+
*
|
|
8696
|
+
* Refused (VfsConflictError) for anything a share cannot take whole: not a folder; `/`, `/Home`, a link, or
|
|
8697
|
+
* a place in a share; a folder holding a link, an entry this version cannot read, or one half of a move that
|
|
8698
|
+
* did not finish; a folder or file named in two places inside it.
|
|
8699
|
+
*/
|
|
8700
|
+
private sharingPlan;
|
|
8701
|
+
/**
|
|
8702
|
+
* Mark the folder at `path` (still the folder `dirId`) as being moved into the share `spaceId`, so a run that
|
|
8703
|
+
* stops part-way resumes into the same share. Replaces an earlier mark (a share that moved on to a successor).
|
|
8704
|
+
*/
|
|
8705
|
+
private markSharing;
|
|
8706
|
+
/**
|
|
8707
|
+
* The last step of sharing a folder: replace the folder at `path` - still the folder `dirId`, still marked as
|
|
8708
|
+
* going to `spaceId` - with a link to that share, then remove its records. Each file's current content is
|
|
8709
|
+
* NOT let go of here: the files whose records were removed are returned (`detached`) for the caller to let
|
|
8710
|
+
* go of. What is let go of here is each such file's earlier versions, which a share does not keep, and its
|
|
8711
|
+
* history record. A record that, read again from the store just before its removal, holds anything not in
|
|
8712
|
+
* `moved` (another device wrote into it) is left in place and listed in `kept`.
|
|
8713
|
+
*
|
|
8714
|
+
* Refused with VfsConflictError, changing nothing, unless the folder holds exactly what `moved` lists: a file
|
|
8715
|
+
* saved, changed, moved out or deleted since (by its id and manifest id), a new empty folder, a link, an
|
|
8716
|
+
* entry this version cannot read, or a move that did not finish. Read the folder again first.
|
|
8717
|
+
*/
|
|
8718
|
+
private finishSharing;
|
|
8719
|
+
/**
|
|
8720
|
+
* Whether `path` is a link, `/Home/Shared`, or inside a share - somewhere the user's own files are not, and
|
|
8721
|
+
* that only `list`, `stat`, `readFile`, `writeFile`, `mkdir`, `delete`, `rename`, `copy` and walks serve.
|
|
8722
|
+
* True for a link even with no shares wired. Version control refuses a project there.
|
|
8723
|
+
*/
|
|
8724
|
+
inShare(path: string): Promise<boolean>;
|
|
8725
|
+
/**
|
|
8726
|
+
* Where `path` leads, with shares wired.
|
|
8727
|
+
*
|
|
8728
|
+
* - `/Home` is virtual for reads: the user's own `/Home` folder (if there is one) plus `Shared`. For a write
|
|
8729
|
+
* (`write`), it is that real folder, made when first written into. A real `/Home` that is not a folder is
|
|
8730
|
+
* just that entry.
|
|
8731
|
+
* - `/Home/Shared` lists the shares; `/Home/Shared/<name>/...` is inside the share listed as `<name>`
|
|
8732
|
+
* (VfsNotFoundError when there is none). The user's own `/Home/Shared`, if they have one, is reached as
|
|
8733
|
+
* `/Home/Shared (yours)` (see `sharedAlias`).
|
|
8734
|
+
* - A path that passes through a link is inside that link's share. `follow` also follows a link AT the path
|
|
8735
|
+
* (list, walk, read, cd); without it the path is the link itself (stat, delete, rename, writeFile).
|
|
8736
|
+
* - Anything else is the user's own tree, unchanged.
|
|
8737
|
+
*
|
|
8738
|
+
* Records that cannot be read on the way are left to the operation to report, as it always has.
|
|
8739
|
+
*
|
|
8740
|
+
* A write (`write`, unless `guard` is false - a copy's source is only read) to `/Home/Shared/<X>/...` is
|
|
8741
|
+
* refused when the user's own `/Home/Shared` holds `<X>`: until shares came, that path WAS their folder, and
|
|
8742
|
+
* a mount, a script or a bookmark that still means it would otherwise write personal files into a share, or
|
|
8743
|
+
* delete a share's files. Reads still go to the share.
|
|
8744
|
+
*/
|
|
8745
|
+
private route;
|
|
8746
|
+
/** The first link among the first `upto` names of `parts`, followed from the root, and where it is. */
|
|
8747
|
+
private linkOnTheWay;
|
|
8748
|
+
/**
|
|
8749
|
+
* The user's own `/Home/Shared` holds `name`: refuse a write to `target`, which is `/Home/Shared/<name>/...`.
|
|
8750
|
+
* See `route`.
|
|
8751
|
+
*/
|
|
8752
|
+
private refuseStaleSharedPath;
|
|
8753
|
+
/**
|
|
8754
|
+
* Both ends of a move or a copy. A destination in `/Home/Shared` that names no share is across a boundary.
|
|
8755
|
+
* `sourceIsRead`: a copy, whose source is only read.
|
|
8756
|
+
*/
|
|
8757
|
+
private routeEnds;
|
|
8758
|
+
/**
|
|
8759
|
+
* `path` in the user's own tree, for an operation that has no meaning in a share (`what` says why). Without
|
|
8760
|
+
* shares, the path as it is.
|
|
8761
|
+
*/
|
|
8762
|
+
private ownPath;
|
|
8763
|
+
/** `/Home` is the Home folder: only a folder may be moved or copied there. */
|
|
8764
|
+
private refuseNonDirAtHome;
|
|
8765
|
+
/** The user's own `/Home` entry, and its record when it is a folder. */
|
|
8766
|
+
private realHome;
|
|
8767
|
+
/**
|
|
8768
|
+
* The name the user's own `/Home/Shared` is shown and reached under - `Shared (yours)`, or the first of
|
|
8769
|
+
* `Shared (yours 2)`, `Shared (yours 3)`... not taken in `/Home` - or null when they have none.
|
|
8770
|
+
*/
|
|
8771
|
+
private sharedAlias;
|
|
8772
|
+
/** Rewrites a stat of the user's own `/Home/Shared`, or of anything in it, to the path it is shown under. */
|
|
8773
|
+
private shownPaths;
|
|
8774
|
+
/** `/Home`'s listing: the user's own `/Home` folder, if any, and `Shared`. */
|
|
8775
|
+
private listHome;
|
|
7567
8776
|
private expectFile;
|
|
7568
8777
|
/** Resolve a path to its entry, or null. Root has no entry of its own. */
|
|
7569
8778
|
private find;
|
|
@@ -7825,6 +9034,17 @@ declare class VfsNamespace {
|
|
|
7825
9034
|
* elsewhere is kept, and so is a file.
|
|
7826
9035
|
*/
|
|
7827
9036
|
private purge;
|
|
9037
|
+
/**
|
|
9038
|
+
* Remove the records of a folder that has just been replaced by a link to the share its files went to (see
|
|
9039
|
+
* `finishSharing`), and return the files whose records went, for the caller to let go of their content.
|
|
9040
|
+
*
|
|
9041
|
+
* Each record is read again from the store, past the cache, just before it is removed: the checks before the
|
|
9042
|
+
* swap looked at this device's copies, and another device may have written into one since. A record that now
|
|
9043
|
+
* holds anything not in `moved` (or cannot be read) is left in place, with a warning, and its files are not
|
|
9044
|
+
* returned. Otherwise each file's earlier versions are let go of and its history record removed. Best-effort,
|
|
9045
|
+
* like `purge`: a failure leaks storage, never loses anything.
|
|
9046
|
+
*/
|
|
9047
|
+
private purgeShared;
|
|
7828
9048
|
/**
|
|
7829
9049
|
* Unmark what is left of an interrupted move once a delete has removed
|
|
7830
9050
|
* the other copy. Marked, a file keeps every version that falls off its
|
|
@@ -8064,6 +9284,12 @@ declare class Repo {
|
|
|
8064
9284
|
private readonly maxTreeDepth;
|
|
8065
9285
|
constructor(slug: string, deps: VcsNamespaceDeps);
|
|
8066
9286
|
private get root();
|
|
9287
|
+
/**
|
|
9288
|
+
* Refuse a project whose working tree is a link or inside a shared folder. A share's files have no content
|
|
9289
|
+
* handles the repository could record, so a commit there would hold no files, and a checkout of it would
|
|
9290
|
+
* delete every file in the share.
|
|
9291
|
+
*/
|
|
9292
|
+
private assertOwnTree;
|
|
8067
9293
|
/** Store an object, returning its hash and whether it was new. */
|
|
8068
9294
|
private put;
|
|
8069
9295
|
/** Does this stored record open to an object with this hash? */
|
|
@@ -8323,6 +9549,12 @@ interface ClientOptions {
|
|
|
8323
9549
|
sessionStore?: SessionStore;
|
|
8324
9550
|
/** Custom fetch — defaults to `globalThis.fetch`. */
|
|
8325
9551
|
fetch?: typeof fetch;
|
|
9552
|
+
/**
|
|
9553
|
+
* Where `client.shares` keeps its per-device state: the device login of a guest account it made (see
|
|
9554
|
+
* {@link SharesNamespace.joinWithPassword}), an unfinished guest setup or rotation. Defaults to `localStorage`
|
|
9555
|
+
* in a browser (keyed by the app key and accelerator), memory elsewhere.
|
|
9556
|
+
*/
|
|
9557
|
+
sharesStore?: SharesLocalStore;
|
|
8326
9558
|
/** Optional log level for the SDK logger. */
|
|
8327
9559
|
logLevel?: string;
|
|
8328
9560
|
/**
|
|
@@ -8387,6 +9619,8 @@ declare class Client {
|
|
|
8387
9619
|
readonly message: MessageNamespace;
|
|
8388
9620
|
/** Fan-out group spaces — `client.space.createSpace(...)`, etc. */
|
|
8389
9621
|
readonly space: SpaceNamespace;
|
|
9622
|
+
/** Shared folders — `client.shares.create(...)`, `client.shares.joinWithPassword(...)`, etc. */
|
|
9623
|
+
readonly shares: SharesNamespace;
|
|
8390
9624
|
/** Trust records shared by every Space: pins and per-Space log heads (design §3.4, §6.9). */
|
|
8391
9625
|
readonly trust: {
|
|
8392
9626
|
readonly persistent: boolean;
|
|
@@ -8401,6 +9635,8 @@ declare class Client {
|
|
|
8401
9635
|
readonly accessTokens: AccessTokensNamespace;
|
|
8402
9636
|
/** This app — `client.app.access()`: may the signed-in user add data here? */
|
|
8403
9637
|
readonly app: AppNamespace;
|
|
9638
|
+
/** Vector search — `client.vectors.collection("docs").query({ text })`, plus owner management of collections. */
|
|
9639
|
+
readonly vectors: VectorsNamespace;
|
|
8404
9640
|
/** Offline cache + sync — `client.offline.status`, `client.offline.snapshot`, etc. */
|
|
8405
9641
|
readonly offline: OfflineManager;
|
|
8406
9642
|
private readonly session;
|
|
@@ -9687,7 +10923,7 @@ declare function getId(row: {
|
|
|
9687
10923
|
* expect (and isn't serving a stale cached bundle). Keep this in sync with
|
|
9688
10924
|
* `package.json` `version`.
|
|
9689
10925
|
*/
|
|
9690
|
-
declare const VERSION = "0.15.0-alpha.
|
|
10926
|
+
declare const VERSION = "0.15.0-alpha.12";
|
|
9691
10927
|
|
|
9692
10928
|
/**
|
|
9693
10929
|
* The SDK's process-global logger.
|
|
@@ -9719,5 +10955,5 @@ declare global {
|
|
|
9719
10955
|
}
|
|
9720
10956
|
declare const appLogger: InstanceType<typeof Logger>;
|
|
9721
10957
|
|
|
9722
|
-
export { ACCESS_TOKEN_SCOPES, AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES, AccessTokensNamespace, AdmissionDeniedError, AgentsNamespace, AppNamespace, AuthClient, AuthHttpError, AuthNamespace, AuthPublicInput, Authenticator, BlockEngine, BroadcastChannel, BroadcastChannelEvents, ChannelExistsError, ChannelNotFoundError, ChunkCipher, CircuitIntegrityError, Client, ConnectivityManager, DEFAULT_AUTH_BASE_URL, DEFAULT_BASE_URL, DEFAULT_BRANCH, DEFAULT_FN_HOST_SUFFIX, DEVICE_IDENTITY_STORAGE_KEY, DEVICE_KEY_DB_NAME, DbCache, DbNamespace, DbTable, DevicePairingError, DeviceRevokedError, DeviceStoreUnavailableError, DoubleRatchet, DoubleRatchetCipher, DoubleRatchetManager, EncryptedSession, EventCore, EventCoreEvents, Field, Field as FieldElement, FileStorage, FunctionsNamespace, HLC, HashKnowledge, HostedAuth, HttpClient, HttpError, IdentityLockedError, IdentityUnavailableError, IndexedDbStore, KEEPER_MEMBER_ID, KeyStore, KeyringClient, KeyringHttpError, KvCache, KvNamespace, LocalEngineHost, LocalStorageSessionStore, Logger, MemorySessionStore, Message, Message as MessageDefault, MessageNamespace, MuhkooAgent, MuhkooDB, MuhkooFunction, MuhkooSpace, NOT_MEMBER_CLOSE_CODE, NOT_MEMBER_RECHECK_MS, NoopStore, OfflineLockedError, OfflineManager, OutboundQueue, P2P_SUBJECT, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, PBKDF2_DEFAULT_ITERATIONS, PINNED_CIRCUIT_DIGESTS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PasskeyOriginError, PaymentRequiredError, PeerExchange, PeerNetwork, PersonalSpaceClient, Poseidon, PreimagePoK, ROOT_ID, Ready, ReauthRequiredError, ReedSolomonCodec, Repo, Retry, Space as Room, SerializeMessage, SessionState, ShardCache, ShardClient, SharedSpaceClient, SnapshotNamespace, Space, SpaceCache, SpaceKeyring, SpaceNamespace, SpacePacketCipher, SpaceSignaler, SpaceTrustError, StorageNamespace, SyncEngine, VERSION, VFS_ROOT_INFO, VaultProtocolMismatchError, VaultUnavailableError, VcsError, VcsNamespace, VfsConflictError, VfsCorruptRecordError, VfsLimitError, VfsLockedError, VfsNamespace, VfsNotFoundError, WSTransport, WebRtcTransport, WorkerEngineHost, ZERO_HLC, ZkAuth, _accountId, _formatBytes, _messageId, _objectId, _packetId, _socketId, _userId, appLogger, assertType, base58Decode, base58Encode, buildCommitment, canonicalUserCode, clearDeviceIdentity, compareHlc, compilePrograms, concatBytes, configureDeviceStore, createPasskeyWithPrf, decodeFromHex, decorators, decryptAesGcm, defaultCircuitUrls, defaultRpId, defaultSessionStore, deleteBeatsWrite, deleteRegister, deriveAesKeyFromPassphrase, deriveBitsHkdf, deriveIdentity, deriveIdentityFromSeed, deriveMasterSeedFromPassword, deserialize, deviceFingerprint, deviceIdentityIsEphemeral, deviceIdentityKey, dirKey, ejectAgentPrompt, ejectAgentTools, emptyMap, emptyRegister, encodeToHex, encryptAesGcm, evaluatePasskeyPrf, exportPublicKeyBase64, exportPublicKeyHex, formatUserCode, fromBase64, fromBase64Url, fromHex, generateAuthProof, generateChecksum, generateDevicePairingKeypair, generateId, generatePkce, getIPAddress, getId, getMuhkooAppDescriptor, getSubtle, hasDeviceIdentity, headKey, historyKey, initBn128Wasm, initRsWasm, initializeCircuits, isNewer, isNumber, isOfflineCapable, isP2pCapable, isProvisional, isSameOriginPath, loadDeviceIdentity, log, manifestToStat, materializeRow, merge3, merge3Text, mergeKey, mergeMap, mergeMessage, mergeRegister, messageKey, objectKey, pack, padHandle, pairingVerificationCode, passkeyPrfCapable, passkeySupported, passkeyUsableFromOrigin, persistDeviceIdentity, poseidonHash, protocol, provisionalHandle, quickVerify, randomBytes, randomState, refKey, refsIndexKey, rpIdUsableForOrigin, sealSeed, sealSeedToDevice, serialize, shardHash, signMessage, stableStringify, toBase64, toBase64Url, toField, toHex, tombstoneRow, unpack, unsealSeed, unsealSeedFromDevice, unwrapWithPassphrase, utf8Decode, utf8Encode, verify, verifyChecksum, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase, writeBeatsTombstone, writeColumns, writeRegister };
|
|
9723
|
-
export type { ACL, ACLEntry, AccessTokenInfo, AccessTokensNamespaceDeps, AdmissionState, AgentConfig, AgentCreateInput, AgentDbToolMode, AgentProvisioned, AgentScopeOpts, AgentSkill, AgentToolsConfig, AgentTrigger, AgentTriggerType, AgentUpdateInput, AgentsNamespaceDeps, AppAccess, AppNamespaceDeps, AttachedPeerNetwork, AuthClientOptions, AuthKeyPair, AuthSuccess, AuthToken, AuthType, AuthUser, BlockStore, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, CachedSpaceMessage, Change, ChannelLike, ChatKeyCert, ChunkKeyMaterial, ChunkManifest, CipherFrame, CipherMessage, CipherMessageHeader, CircuitBufferConfig, CircuitIntegrity, CircuitUrls, ClientOptions, Commit, Conflict, ConnectivityOptions, ConnectivityState, CreateAccessTokenInput, CreatedAccessToken, DbFilterOp, DbNamespaceDeps, DbQuery, DbQueryPage, DbQueryResult, DbWhereCondition, DehydratedKeypair, DehydratedKeys, DeviceBlobStore, DeviceKeyVault, DevicePairingErrorReason, DevicePairingKeypair, DevicePairingPoll, DevicePairingRequest, DevicePairingSession, DirEntry, DirNode, DoubleRatchetCipherDeps, ECDHCurve, EncodeResult, EngineHandle, EngineHost, Entry, EphemeralEvent, EpochKeyProvider, FileEntry, FileManifest, FileNamespaceDeps, FileStat, FileStorageOptions, FunctionCaps, FunctionConfig, FunctionDeployInput, FunctionInvokeOptions, FunctionScopeOpts, FunctionTrigger, FunctionTriggerType, FunctionTriggers, FunctionUpdateInput, FunctionsNamespaceDeps, Groth16Proof, Hasher, Head, HistoryRecord, HlcParts, HlcState, HostedAuthDeps, HttpClientOptions, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, KeyringClientDeps, KeyringTransport, KvEntry, KvNamespaceDeps, LogEntry, LoginOptions, LwwMap, LwwRegister, MemberView, MembershipEntry, Merge3Result, MergeRegionConflict, MergeResult, 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, PaymentRequiredCode, PeerBlockSource, PeerExchangeOptions, PeerId, PeerNetworkOptions, PeerTransport, Permission, PermissionCheckRequest, PermissionCheckResult, PersistedDeviceIdentity, PersonalSpaceClientOptions, Pkce, PublicKeyJWK, QueueEntry, RatchetState, ReceiveResult, RegisterParams, Replayer, Role$1 as Role, SpaceDeps as RoomDeps, SpaceFileMetadata as RoomFileMetadata, Scope, SealedHandoff, SealedHeaders, SealedRecord, Session, SessionOptions, SessionStore, SetOptions, ShardByteCache, ShardClientOptions, SharedSpaceClientOptions, SignalEnvelope, SignalKind, SignalingSpace, SnapshotNamespaceDeps, SnarkProof, SpaceChannelLike, SpaceCursor, SpaceDeps, SpaceFileMetadata, SpaceKeyCache, SpaceKeyringDeps, SpaceMessageEvent, SpaceNamespaceDeps, SpaceOfflineAdapter, SpaceTrustCode, StartDevicePairingOptions, StorageChangeEvent, StoreName, StoredSession, Subscription, Tree, TreeDir, TreeEntry, TreeFile, UserIdentity, VaultFactor, VcsNamespaceDeps, VcsNamespaceOptions, VerificationKey, VfsContentStore, VfsNamespaceDeps, VfsStat, VfsStore, WSMessage, WSMessageType, WSTransportOptions, WaitForDevicePairingOptions, WebRtcTransportOptions, WrappedPayload, WriteFileInput, WriteFileOptions, WriteToShardsInput, ZkAuthDeps, ZkAuthenticateRequest, ZkChallengeResponse, ZkCompiled, ZkIdentity, ZkRegisterRequest, ZkRegisterResponse };
|
|
10958
|
+
export { ACCESS_TOKEN_SCOPES, AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES, AccessTokensNamespace, AdmissionDeniedError, AgentsNamespace, AppNamespace, AuthClient, AuthHttpError, AuthNamespace, AuthPublicInput, Authenticator, BlockEngine, BroadcastChannel, BroadcastChannelEvents, ChannelExistsError, ChannelNotFoundError, ChunkCipher, CircuitIntegrityError, Client, ConnectivityManager, DEFAULT_AUTH_BASE_URL, DEFAULT_BASE_URL, DEFAULT_BRANCH, DEFAULT_FN_HOST_SUFFIX, DEVICE_IDENTITY_STORAGE_KEY, DEVICE_KEY_DB_NAME, DbCache, DbNamespace, DbTable, DevicePairingError, DeviceRevokedError, DeviceStoreUnavailableError, DoubleRatchet, DoubleRatchetCipher, DoubleRatchetManager, EncryptedSession, EventCore, EventCoreEvents, Field, Field as FieldElement, FileStorage, FunctionsNamespace, GoogleNotLinkedError, GuestLoginConflictError, HLC, HashKnowledge, HostedAuth, HttpClient, HttpError, IdentityLockedError, IdentityUnavailableError, IndexedDbStore, InvalidRecoveryCodeError, KEEPER_MEMBER_ID, KeyStore, KeyringClient, KeyringHttpError, KvCache, KvNamespace, LocalEngineHost, LocalStorageSessionStore, Logger, MAX_SHARE_SUCCESSOR_HOPS, MemorySessionStore, Message, Message as MessageDefault, MessageNamespace, MuhkooAgent, MuhkooDB, MuhkooFunction, MuhkooSpace, NOT_MEMBER_CLOSE_CODE, NOT_MEMBER_RECHECK_MS, NoopStore, OfflineLockedError, OfflineManager, OutboundQueue, P2P_SUBJECT, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, PBKDF2_DEFAULT_ITERATIONS, PINNED_CIRCUIT_DIGESTS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PasskeyOriginError, PaymentRequiredError, PeerExchange, PeerNetwork, PersonalSpaceClient, Poseidon, PreimagePoK, ROOT_ID, Ready, ReauthRequiredError, ReedSolomonCodec, Repo, Retry, Space as Room, RotationInProgressError, RotationIncompleteError, RotationMismatchError, SHARE_DIR_TYPE, SHARE_GUEST_DEVICE_LABEL, SHARE_PASSWORD_ITERATIONS, SerializeMessage, SessionState, ShardCache, ShardClient, Share, ShareClosedError, ShareFullError, ShareMemberLimitError, SharePasswordError, SharePasswordRateError, ShareSpaceNotEmptyError, ShareSpaceNotReadyError, SharedSpaceClient, SharesClient, SharesNamespace, SnapshotNamespace, Space, SpaceCache, SpaceKeyring, SpaceNamespace, SpacePacketCipher, SpaceSignaler, SpaceTrustError, StorageNamespace, SyncEngine, VERSION, VFS_ROOT_INFO, VaultProtocolMismatchError, VaultUnavailableError, VcsError, VcsNamespace, VectorCollection, VectorCollectionFailedError, VectorWaitTimeoutError, VectorsNamespace, VfsConflictError, VfsCorruptRecordError, VfsLimitError, VfsLockedError, VfsNamespace, VfsNotFoundError, WSTransport, WebRtcTransport, WorkerEngineHost, ZERO_HLC, ZkAuth, _accountId, _formatBytes, _messageId, _objectId, _packetId, _socketId, _userId, appLogger, assertType, base58Decode, base58Encode, buildCommitment, canonicalUserCode, clearDeviceIdentity, compareHlc, compilePrograms, concatBytes, configureDeviceStore, createPasskeyWithPrf, decodeFromHex, decorators, decryptAesGcm, defaultCircuitUrls, defaultRpId, defaultSessionStore, defaultSharesStore, deleteBeatsWrite, deleteRegister, deriveAesKeyFromPassphrase, deriveBitsHkdf, deriveIdentity, deriveIdentityFromSeed, deriveMasterSeedFromPassword, deserialize, deviceFingerprint, deviceIdentityIsEphemeral, deviceIdentityKey, dirKey, ejectAgentPrompt, ejectAgentTools, emptyMap, emptyRegister, encodeToHex, encryptAesGcm, evaluatePasskeyPrf, exportPublicKeyBase64, exportPublicKeyHex, formatUserCode, fromBase64, fromBase64Url, fromHex, generateAuthProof, generateChecksum, generateDevicePairingKeypair, generateId, generatePkce, getIPAddress, getId, getMuhkooAppDescriptor, getSubtle, guestRecoveryCode, guestRecoveryOf, hasDeviceIdentity, headKey, historyKey, initBn128Wasm, initRsWasm, initializeCircuits, isNewer, isNumber, isOfflineCapable, isP2pCapable, isProvisional, isSameOriginPath, loadDeviceIdentity, log, manifestToStat, materializeRow, memorySharesStore, merge3, merge3Text, mergeKey, mergeMap, mergeMessage, mergeRegister, messageKey, newPasswordVerifier, objectKey, pack, padHandle, pairingVerificationCode, parseGuestRecoveryCode, passkeyPrfCapable, passkeySupported, passkeyUsableFromOrigin, passwordProof, persistDeviceIdentity, poseidonHash, protocol, provisionalHandle, quickVerify, randomBytes, randomState, refKey, refsIndexKey, rpIdUsableForOrigin, sealSeed, sealSeedToDevice, serialize, shardHash, shareErrorFrom, signMessage, stableStringify, toBase64, toBase64Url, toField, toHex, tombstoneRow, unpack, unsealSeed, unsealSeedFromDevice, unwrapWithPassphrase, utf8Decode, utf8Encode, verify, verifyChecksum, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase, writeBeatsTombstone, writeColumns, writeRegister };
|
|
10959
|
+
export type { ACL, ACLEntry, AccessTokenInfo, AccessTokensNamespaceDeps, AdmissionState, AgentConfig, AgentCreateInput, AgentDbToolMode, AgentProvisioned, AgentScopeOpts, AgentSkill, AgentToolsConfig, AgentTrigger, AgentTriggerType, AgentUpdateInput, AgentsNamespaceDeps, AppAccess, AppNamespaceDeps, AttachedPeerNetwork, AuthClientOptions, AuthKeyPair, AuthSuccess, AuthToken, AuthType, AuthUser, BlockStore, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, CachedSpaceMessage, Change, ChannelLike, ChatKeyCert, ChunkKeyMaterial, ChunkManifest, CipherFrame, CipherMessage, CipherMessageHeader, CircuitBufferConfig, CircuitIntegrity, CircuitUrls, ClientOptions, Commit, Conflict, ConnectivityOptions, ConnectivityState, CreateAccessTokenInput, CreateShareBody, CreateShareOptions, CreatedAccessToken, DbFilterOp, DbNamespaceDeps, DbQuery, DbQueryPage, DbQueryResult, DbWhereCondition, DehydratedKeypair, DehydratedKeys, DeviceBlobStore, DeviceKeyVault, DevicePairingErrorReason, DevicePairingKeypair, DevicePairingPoll, DevicePairingRequest, DevicePairingSession, DirEntry, DirNode, DoubleRatchetCipherDeps, ECDHCurve, EditPolicy, EncodeResult, EngineHandle, EngineHost, Entry, EphemeralEvent, EpochKeyProvider, FileEntry, FileManifest, FileNamespaceDeps, FileStat, FileStorageOptions, FunctionCaps, FunctionConfig, FunctionDeployInput, FunctionInvokeOptions, FunctionScopeOpts, FunctionTrigger, FunctionTriggerType, FunctionTriggers, FunctionUpdateInput, FunctionsNamespaceDeps, Groth16Proof, GuestDeviceLogin, GuestRecovery, Hasher, Head, HistoryRecord, HlcParts, HlcState, HostedAuthDeps, HttpClientOptions, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, KeyringClientDeps, KeyringTransport, KvEntry, KvNamespaceDeps, LinkEntry, LogEntry, LoginOptions, LwwMap, LwwRegister, MemberView, MembershipEntry, Merge3Result, MergeRegionConflict, MergeResult, 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, PasswordVerifier, PaymentRequiredCode, PeerBlockSource, PeerExchangeOptions, PeerId, PeerNetworkOptions, PeerTransport, Permission, PermissionCheckRequest, PermissionCheckResult, PersistedDeviceIdentity, PersonalSpaceClientOptions, Pkce, PublicKeyJWK, QueueEntry, RatchetState, ReceiveResult, RegisterParams, Replayer, Role$1 as Role, SpaceDeps as RoomDeps, SpaceFileMetadata as RoomFileMetadata, Scope, SealedHandoff, SealedHeaders, SealedRecord, Session, SessionOptions, SessionStore, SetOptions, ShardByteCache, ShardClientOptions, ShareAdmitBody, ShareAdoptFile, ShareAdoptItem, ShareEntry, ShareFolderOptions, ShareGuestAuth, ShareInfo, ShareKind, ShareOptions, SharePublicInfo, ShareSpaceHandle, ShareSpaceKeyring, ShareSpaces, ShareSummary, SharedSpaceClientOptions, SharesLocalStore, SharesNamespaceDeps, SignalEnvelope, SignalKind, SignalingSpace, SnapshotNamespaceDeps, SnarkProof, SpaceChannelLike, SpaceCursor, SpaceDeps, SpaceFileMetadata, SpaceKeyCache, SpaceKeyringDeps, SpaceMessageEvent, SpaceNamespaceDeps, SpaceOfflineAdapter, SpaceTrustCode, StartDevicePairingOptions, StorageChangeEvent, StoreName, StoredSession, Subscription, Tree, TreeDir, TreeEntry, TreeFile, UserIdentity, VaultFactor, VcsNamespaceDeps, VcsNamespaceOptions, VectorAudience, VectorCollectionDefinition, VectorCollectionInfo, VectorEntry, VectorEntryInput, VectorEnvInfo, VectorFieldDefinition, VectorMatch, VectorNotices, VectorNotify, VectorQueryInput, VectorReadyEvent, VectorUpsertOptions, VectorWriteResult, VectorWriteState, VectorsNamespaceDeps, VerificationKey, VfsContentStore, VfsNamespaceDeps, VfsStat, VfsStore, WSMessage, WSMessageType, WSTransportOptions, WaitForDevicePairingOptions, WebRtcTransportOptions, WrappedPayload, WriteFileInput, WriteFileOptions, WriteToShardsInput, ZkAuthDeps, ZkAuthenticateRequest, ZkChallengeResponse, ZkCompiled, ZkIdentity, ZkRegisterRequest, ZkRegisterResponse };
|