@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.
@@ -1232,6 +1232,310 @@ declare class PaymentRequiredError extends HttpError {
1232
1232
  constructor(message: string, code: PaymentRequiredCode, body?: unknown, upgradeUrl?: string);
1233
1233
  }
1234
1234
 
1235
+ /**
1236
+ * Wire types for shared folders. These mirror the accelerator's `/api/shares` JSON
1237
+ * (`ShareInfo` in the accelerator's `durable-objects/space/share.ts`).
1238
+ */
1239
+ type ShareKind = "public" | "private";
1240
+ /** Who may change a file: `own` = its uploader and the owner; `any` = any member (private shares only). */
1241
+ type EditPolicy = "own" | "any";
1242
+ interface ShareInfo {
1243
+ kind: ShareKind;
1244
+ ownerUsername: string;
1245
+ /** Storage cap in bytes, or null for no cap. */
1246
+ limitBytes: number | null;
1247
+ usedBytes: number;
1248
+ editPolicy: EditPolicy;
1249
+ name: string;
1250
+ /** Set once the share was rotated into another Space; follow `successor`. */
1251
+ closed: {
1252
+ successor: string;
1253
+ at: number;
1254
+ } | null;
1255
+ /** The member list (usernames). */
1256
+ members: string[];
1257
+ /**
1258
+ * Display names by username, for uploaders and admitted members: label files by their `owner` with it. After a
1259
+ * rotation it also holds uploaders not (yet) re-admitted, so it is not the member list.
1260
+ */
1261
+ names: Record<string, string>;
1262
+ }
1263
+ /** One row of `GET /api/shares`. */
1264
+ interface ShareSummary {
1265
+ spaceId: string;
1266
+ kind: ShareKind;
1267
+ owner: string;
1268
+ name: string;
1269
+ }
1270
+ /** The password verifier the server stores for a public share (`proof` is derived from it). */
1271
+ type PasswordVerifier = {
1272
+ salt: string;
1273
+ iterations: number;
1274
+ verifier: string;
1275
+ };
1276
+ /** `GET /api/shares/:spaceId/public`: what a guest needs before being admitted (app key only, no session). */
1277
+ interface SharePublicInfo {
1278
+ kind: "public";
1279
+ name: string;
1280
+ ownerUsername: string;
1281
+ password: {
1282
+ salt: string;
1283
+ iterations: number;
1284
+ };
1285
+ closed: {
1286
+ successor: string;
1287
+ at: number;
1288
+ } | null;
1289
+ }
1290
+ interface CreateShareBody {
1291
+ spaceId: string;
1292
+ kind: ShareKind;
1293
+ name: string;
1294
+ limitBytes: number | null;
1295
+ editPolicy: EditPolicy;
1296
+ password?: PasswordVerifier;
1297
+ }
1298
+ /** `POST /api/shares/:spaceId/admit`, sent with the signed-in account's session. */
1299
+ interface ShareAdmitBody {
1300
+ /** `passwordProof(password, salt, iterations)` with the share's public salt and iterations. */
1301
+ proof: string;
1302
+ /** The display name shown next to this member's uploads: 1–40 characters after trimming, no control characters. */
1303
+ name: string;
1304
+ }
1305
+
1306
+ /**
1307
+ * Typed refusals from the shares API. Each extends {@link HttpError}, so code that only knows `HttpError` still
1308
+ * sees the status and body. Codes are the accelerator's wire contract.
1309
+ */
1310
+
1311
+ /** 402 `share_full`: the share is at its storage cap. */
1312
+ declare class ShareFullError extends HttpError {
1313
+ readonly limitBytes: number;
1314
+ readonly usedBytes: number;
1315
+ /**
1316
+ * How many items of a `Share.writeMany` were not written (the refused one and every one after it). The
1317
+ * server's body has no such field, so it is 0 on an error straight from the wire.
1318
+ */
1319
+ readonly refused: number;
1320
+ constructor(message: string, limitBytes: number, usedBytes: number,
1321
+ /**
1322
+ * How many items of a `Share.writeMany` were not written (the refused one and every one after it). The
1323
+ * server's body has no such field, so it is 0 on an error straight from the wire.
1324
+ */
1325
+ refused: number, body?: unknown);
1326
+ }
1327
+ /** 409 `share_closed`: the share was rotated; use `successor` instead. */
1328
+ declare class ShareClosedError extends HttpError {
1329
+ readonly successor: string;
1330
+ constructor(message: string, successor: string, body?: unknown);
1331
+ }
1332
+ /** 403 `share_password`: wrong password. */
1333
+ declare class SharePasswordError extends HttpError {
1334
+ constructor(message: string, body?: unknown);
1335
+ }
1336
+ /** 429 `share_password_rate`: too many wrong passwords. */
1337
+ declare class SharePasswordRateError extends HttpError {
1338
+ readonly retryAfterSeconds: number;
1339
+ constructor(message: string, retryAfterSeconds: number, body?: unknown);
1340
+ }
1341
+ /** 403 `share_member_limit`: the share holds as many members as it allows. */
1342
+ declare class ShareMemberLimitError extends HttpError {
1343
+ constructor(message: string, body?: unknown);
1344
+ }
1345
+ /** 409 `share_space_not_empty`: only an empty Space can become a share. */
1346
+ declare class ShareSpaceNotEmptyError extends HttpError {
1347
+ constructor(message: string, body?: unknown);
1348
+ }
1349
+ /** 409 `share_space_not_ready`: the Space has no `/metadata` yet; create the Space before making it a share. */
1350
+ declare class ShareSpaceNotReadyError extends HttpError {
1351
+ constructor(message: string, body?: unknown);
1352
+ }
1353
+ /** 409 `rotation_mismatch`: a retried rotation asked for other settings than the one in progress. */
1354
+ declare class RotationMismatchError extends HttpError {
1355
+ constructor(message: string, body?: unknown);
1356
+ }
1357
+ /** 409 `rotation_in_progress`: another rotation of this share won; `successor` is its new Space. */
1358
+ declare class RotationInProgressError extends HttpError {
1359
+ readonly successor: string;
1360
+ constructor(message: string, successor: string, body?: unknown);
1361
+ }
1362
+ /**
1363
+ * A rotation (`changePassword` / `removeMember`) claimed `newSpaceId` but its adopt did not finish (network failure
1364
+ * or server error, retried). It is kept on this device: call the same rotation again, or `shares.resumeRotation`,
1365
+ * to finish it into the SAME Space. No other rotation of this share starts until it does.
1366
+ */
1367
+ declare class RotationIncompleteError extends Error {
1368
+ readonly from: string;
1369
+ readonly newSpaceId: string;
1370
+ readonly cause?: unknown | undefined;
1371
+ constructor(from: string, newSpaceId: string, cause?: unknown | undefined);
1372
+ }
1373
+ /** A guest recovery code that does not parse (expected `<username>:<words>`). */
1374
+ declare class InvalidRecoveryCodeError extends Error {
1375
+ constructor(message?: string);
1376
+ }
1377
+ /** `restoreGuest` would replace another guest's login kept on this device; pass `{ replace: true }` to do so. */
1378
+ declare class GuestLoginConflictError extends Error {
1379
+ readonly existing: string;
1380
+ constructor(existing: string);
1381
+ }
1382
+ /**
1383
+ * The typed error for a refused response, or null when it is not a share refusal (the caller then throws what it
1384
+ * threw before). `body` is the parsed JSON or the raw response text. `retryAfterSeconds` is the `Retry-After`
1385
+ * header, used for a 429.
1386
+ */
1387
+ declare function shareErrorFrom(status: number, body: unknown, retryAfterSeconds?: number): Error | null;
1388
+
1389
+ /**
1390
+ * `HttpClient` — the one place the unified {@link Client} talks to the
1391
+ * accelerator over HTTP.
1392
+ *
1393
+ * Every request carries two independent credentials:
1394
+ * - the **app key** (`mk_…`) on `X-Muhkoo-Key` — resolves the app /
1395
+ * developer / env context the accelerator uses for routing + billing;
1396
+ * - the **user session token** on `X-Muhkoo-Session` (when a user is
1397
+ * logged in) — the accelerator validates it and injects a trusted
1398
+ * `X-Muhkoo-User-Context` downstream so per-user spaces can authorize
1399
+ * the request without a fresh Groth16 proof.
1400
+ *
1401
+ * `X-Muhkoo-Key` is used (rather than `Authorization: Bearer`) because it is
1402
+ * a non-forbidden header that skips the CORS preflight in browsers.
1403
+ *
1404
+ * The class exposes a header-injecting {@link fetch} that can be handed to
1405
+ * lower-level building blocks (`AuthClient`, `PersonalSpaceClient`) so they
1406
+ * keep owning their own wire shapes while still getting the credentials, plus
1407
+ * convenience JSON helpers (`get`/`post`/`del`) for code that talks to the
1408
+ * accelerator directly.
1409
+ */
1410
+ interface HttpClientOptions {
1411
+ /** Absolute URL of the accelerator worker (trailing slash optional). */
1412
+ baseUrl: string;
1413
+ /**
1414
+ * App / publishable key, e.g. `mk_test_pk_…`. Sent on every request as
1415
+ * `X-Muhkoo-Key` when present. Transitionally optional (auth + personal
1416
+ * storage still function without it), but the product direction is to
1417
+ * REQUIRE it — it attributes traffic for billing/metering and authorizes
1418
+ * shared-space (messaging) websockets.
1419
+ */
1420
+ apiKey?: string;
1421
+ /**
1422
+ * A scoped, expiring **access token** (`mk_<env>_at_…`) — the non-ZK
1423
+ * machine-to-machine credential. It resolves through the SAME accelerator
1424
+ * path as an app key and rides the same `X-Muhkoo-Key` header; when present
1425
+ * it takes precedence over {@link apiKey}. Use it for server-side / CI
1426
+ * callers that shouldn't carry the app's publishable key.
1427
+ */
1428
+ accessToken?: string;
1429
+ /** Returns the current user session token, or `null` when logged out. */
1430
+ getSessionToken?: () => string | null;
1431
+ /** Custom fetch — defaults to `globalThis.fetch`. */
1432
+ fetch?: typeof fetch;
1433
+ /**
1434
+ * Called when a token-gated request comes back `401` (stale/expired
1435
+ * session). Should attempt to silently re-establish a session and resolve
1436
+ * `true` if it succeeded (the request is then retried once with the fresh
1437
+ * token) or `false` if it couldn't (the `401` propagates as an
1438
+ * {@link HttpError}). Wired by {@link Client} to `auth.zk.recover()`.
1439
+ *
1440
+ * Only consulted by the JSON helpers (`get`/`post`/`del`) and
1441
+ * {@link HttpClient.fetchWithRecovery}; the raw {@link fetch} passes 401s
1442
+ * straight through so the auth wire calls that power recovery itself
1443
+ * can't recurse.
1444
+ */
1445
+ onUnauthorized?: () => Promise<boolean>;
1446
+ }
1447
+
1448
+ declare class HttpClient {
1449
+ readonly baseUrl: string;
1450
+ /** Origin of {@link baseUrl} — credentials are only attached same-origin. */
1451
+ private readonly baseOrigin;
1452
+ private readonly apiKey;
1453
+ /** Scoped machine access token — takes precedence over {@link apiKey} on `X-Muhkoo-Key`. */
1454
+ private readonly accessToken;
1455
+ private readonly getSessionToken;
1456
+ private readonly onUnauthorized;
1457
+ private readonly fetchFn;
1458
+ constructor(opts: HttpClientOptions);
1459
+ /**
1460
+ * A `fetch`-compatible function that injects the app key + session token
1461
+ * headers. Hand this to `AuthClient` / `PersonalSpaceClient` so they pick
1462
+ * up credentials without knowing about them.
1463
+ */
1464
+ readonly fetch: typeof fetch;
1465
+ /**
1466
+ * {@link fetch} with the JSON helpers' stale-session recovery: a 401 on a
1467
+ * request made while a session token is held runs `onUnauthorized` once
1468
+ * and, if that recovered, replays the request once with the fresh token.
1469
+ * The final response is returned whatever its status, never thrown. The
1470
+ * replay re-sends `init` as given, so its body must be re-sendable (a
1471
+ * string or bytes, not a stream).
1472
+ */
1473
+ readonly fetchWithRecovery: typeof fetch;
1474
+ /**
1475
+ * A client for the same accelerator and key that never sends a session token and never recovers one. For routes
1476
+ * that need only the app key (a public share's pre-admission info).
1477
+ */
1478
+ withoutSession(): HttpClient;
1479
+ /** True when `input` resolves to {@link baseOrigin} (relative URLs always do). */
1480
+ private isSameOrigin;
1481
+ get<T = unknown>(path: string): Promise<T>;
1482
+ post<T = unknown>(path: string, body?: unknown): Promise<T>;
1483
+ put<T = unknown>(path: string, body?: unknown): Promise<T>;
1484
+ patch<T = unknown>(path: string, body?: unknown): Promise<T>;
1485
+ del<T = unknown>(path: string, body?: unknown): Promise<T>;
1486
+ private request;
1487
+ }
1488
+
1489
+ /**
1490
+ * `SharesClient` — the thin HTTP layer over the accelerator's `/api/shares` routes. It owns paths, verbs and error
1491
+ * mapping and nothing else; the `Share` object and `client.shares` build on it.
1492
+ *
1493
+ * Every call but `publicInfo` carries the app key and the signed-in session (with the usual stale-session recovery),
1494
+ * including `admit`: a public share's guest is an ordinary account. `publicInfo` needs only the app key and never
1495
+ * sends a session.
1496
+ */
1497
+
1498
+ declare class SharesClient {
1499
+ private readonly http;
1500
+ private readonly keyOnlyHttp;
1501
+ constructor(http: HttpClient);
1502
+ create(body: CreateShareBody): Promise<ShareInfo>;
1503
+ list(): Promise<ShareSummary[]>;
1504
+ info(spaceId: string): Promise<ShareInfo>;
1505
+ update(spaceId: string, patch: {
1506
+ limitBytes?: number | null;
1507
+ editPolicy?: EditPolicy;
1508
+ }): Promise<ShareInfo>;
1509
+ /** A public share's name, owner and password salt, read before admission. Publishable key only; never the verifier. */
1510
+ publicInfo(spaceId: string): Promise<SharePublicInfo>;
1511
+ /**
1512
+ * Admit the signed-in account to a public share by proving its password. Afterwards the account is a member:
1513
+ * it sends its own `/keyring/join-request`. Re-admitting the same account only updates its name.
1514
+ */
1515
+ admit(spaceId: string, body: ShareAdmitBody): Promise<void>;
1516
+ removeMember(spaceId: string, username: string): Promise<void>;
1517
+ /** Rotate: `from` is the old share, `newSpaceId` the Space the client made and seeded. */
1518
+ adopt(newSpaceId: string, body: {
1519
+ from: string;
1520
+ password?: PasswordVerifier;
1521
+ remove?: string[];
1522
+ }): Promise<ShareInfo>;
1523
+ private send;
1524
+ }
1525
+
1526
+ /**
1527
+ * Public-share password proof. The password never leaves the device: the guest sends
1528
+ * `proof = base64(PBKDF2-SHA256(password, salt, iterations, 32 bytes))` and the server stores
1529
+ * `verifier = base64(SHA-256(proof bytes))`. The salt is an opaque string chosen at creation time;
1530
+ * both sides use its UTF-8 bytes.
1531
+ */
1532
+
1533
+ declare const SHARE_PASSWORD_ITERATIONS = 310000;
1534
+ /** What a guest sends to prove it knows the password. */
1535
+ declare function passwordProof(password: string, salt: string, iterations: number): Promise<string>;
1536
+ /** What the share owner registers at creation: a fresh salt and the verifier for `password`. */
1537
+ declare function newPasswordVerifier(password: string): Promise<PasswordVerifier>;
1538
+
1235
1539
  /**
1236
1540
  * Cloudflare-Workers-compatible Groth16 ZK proof verifier.
1237
1541
  *
@@ -1274,5 +1578,5 @@ declare function initBn128Wasm(wasmModule?: WebAssembly.Module): Promise<Bn128Wa
1274
1578
  */
1275
1579
  declare function verifyGroth16(wasmInstance: WebAssembly.Instance, memory: WebAssembly.Memory, initialPFree: number, verificationKey: VerificationKey, proof: Groth16Proof, publicSignals: string[]): Promise<boolean>;
1276
1580
 
1277
- export { AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES, BroadcastChannel, BroadcastChannelEvents, ChunkCipher, DoubleRatchet, EncryptedSession, EventCore, EventCoreEvents, KeyStore, Message, Message as MessageDefault, PBKDF2_DEFAULT_ITERATIONS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PaymentRequiredError, SerializeMessage, WSTransport, decorators, decryptAesGcm, deriveAesKeyFromPassphrase, deriveBitsHkdf, encryptAesGcm, getSubtle, initBn128Wasm, randomBytes, unwrapWithPassphrase, verifyGroth16, wrapWithPassphrase };
1278
- export type { ACL, ACLEntry, AuthKeyPair, AuthType, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, ChunkKeyMaterial, CipherFrame, CipherMessage, CipherMessageHeader, DehydratedKeypair, DehydratedKeys, ECDHCurve, Groth16Proof, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, MessageBody, MessageEvent, MessageHeaders, MessageOptions, OAuthProvider, PacketOptions, Participant, PaymentRequiredCode, Permission, PermissionCheckRequest, PermissionCheckResult, PublicKeyJWK, RatchetState, ReceiveResult, Role, Session, SessionOptions, Subscription, UserIdentity, VerificationKey, WSMessage, WSMessageType, WSTransportOptions, WrappedPayload };
1581
+ export { AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES, BroadcastChannel, BroadcastChannelEvents, ChunkCipher, DoubleRatchet, EncryptedSession, EventCore, EventCoreEvents, GuestLoginConflictError, InvalidRecoveryCodeError, KeyStore, Message, Message as MessageDefault, PBKDF2_DEFAULT_ITERATIONS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PaymentRequiredError, RotationInProgressError, RotationIncompleteError, RotationMismatchError, SHARE_PASSWORD_ITERATIONS, SerializeMessage, ShareClosedError, ShareFullError, ShareMemberLimitError, SharePasswordError, SharePasswordRateError, ShareSpaceNotEmptyError, ShareSpaceNotReadyError, SharesClient, WSTransport, decorators, decryptAesGcm, deriveAesKeyFromPassphrase, deriveBitsHkdf, encryptAesGcm, getSubtle, initBn128Wasm, newPasswordVerifier, passwordProof, randomBytes, shareErrorFrom, unwrapWithPassphrase, verifyGroth16, wrapWithPassphrase };
1582
+ export type { ACL, ACLEntry, AuthKeyPair, AuthType, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, ChunkKeyMaterial, CipherFrame, CipherMessage, CipherMessageHeader, CreateShareBody, DehydratedKeypair, DehydratedKeys, ECDHCurve, EditPolicy, Groth16Proof, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, MessageBody, MessageEvent, MessageHeaders, MessageOptions, OAuthProvider, PacketOptions, Participant, PasswordVerifier, PaymentRequiredCode, Permission, PermissionCheckRequest, PermissionCheckResult, PublicKeyJWK, RatchetState, ReceiveResult, Role, Session, SessionOptions, ShareAdmitBody, ShareInfo, ShareKind, SharePublicInfo, ShareSummary, Subscription, UserIdentity, VerificationKey, WSMessage, WSMessageType, WSTransportOptions, WrappedPayload };