@synonymdev/pubky 0.16.2 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@synonymdev/pubky",
3
3
  "type": "module",
4
4
  "description": "Decentralized identity, auth flows, and user-owned storage",
5
- "version": "0.16.2",
5
+ "version": "0.18.0",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
@@ -41,7 +41,7 @@
41
41
  "@types/tape": "^5.6.4",
42
42
  "browser-resolve": "^2.0.0",
43
43
  "browserify": "^17.0.1",
44
- "electron": "41.0.2",
44
+ "electron": "45.1.0",
45
45
  "esmify": "^2.1.1",
46
46
  "tape": "^5.8.1",
47
47
  "tape-run": "^11.0.0",
@@ -52,6 +52,7 @@
52
52
  "fetch-cookie": "^3.0.1"
53
53
  },
54
54
  "overrides": {
55
- "electron": "41.0.2"
55
+ "electron": "45.1.0",
56
+ "minimist": "^1.2.8"
56
57
  }
57
58
  }
package/pubky.d.ts CHANGED
@@ -25,6 +25,33 @@ export interface RecoveredEncryptionKeys {
25
25
 
26
26
 
27
27
 
28
+ /** The individual limits of a quota. A limit is a number, a rate string such as
29
+ * `"100mb/m"`, or `"unlimited"`. Absent in `overrides` means the system default. */
30
+ export interface AccountQuotaLimits {
31
+ /** Storage quota in megabytes, or "unlimited". */
32
+ storageQuotaMb?: number | "unlimited";
33
+ /** Read bandwidth limit, e.g. "100mb/m", or "unlimited". */
34
+ rateRead?: string;
35
+ /** Write bandwidth limit, e.g. "50mb/s", or "unlimited". */
36
+ rateWrite?: string;
37
+ /** Burst allowance for reads, in the rate's unit. Absent means burst equals rate. */
38
+ rateReadBurst?: number;
39
+ /** Burst allowance for writes, in the rate's unit. Absent means burst equals rate. */
40
+ rateWriteBurst?: number;
41
+ /** Path prefixes the user may write to. Absent means unrestricted; empty means read-only. */
42
+ allowedWritePaths?: string[];
43
+ }
44
+
45
+ /** A user's quota, both as it applies and as it was customised. */
46
+ export interface AccountQuota {
47
+ /** Overrides merged with the homeserver's defaults. */
48
+ effective: AccountQuotaLimits;
49
+ /** Only the per-user overrides. */
50
+ overrides: AccountQuotaLimits;
51
+ }
52
+
53
+
54
+
28
55
  export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
29
56
  /** Root-signed grant claims. Public keys are z-base-32; times are Unix seconds. */
30
57
  export interface VerifiedGrantClaims {
@@ -45,7 +72,7 @@ export interface VerifiedGrantClaims {
45
72
  * Provides a simplified, actionable set of error categories for developers
46
73
  * to handle in their code.
47
74
  */
48
- export type PubkyErrorName = "RequestError" | "InvalidInput" | "AuthenticationError" | "PkarrError" | "ClientStateError" | "InternalError";
75
+ export type PubkyErrorName = "RequestError" | "CredentialRefreshError" | "InvalidInput" | "AuthenticationError" | "PkarrError" | "ClientStateError" | "InternalError";
49
76
 
50
77
  /**
51
78
  * Optional x-callback-url metadata carried by a Pubky deep link.
@@ -96,6 +123,15 @@ export interface GrantAuthFlowOptions {
96
123
  * `signedApprovalV1` sets `af=v1` in the authorization link.
97
124
  */
98
125
  approvalFormat?: GrantApprovalFormat;
126
+ /**
127
+ * Optional expected identity: public key of the signed-in user that must
128
+ * approve, as raw z32 or `pubky<z32>`. Set it only when the app already
129
+ * knows the user, e.g. to re-authorize or request more capabilities. It
130
+ * adds `spk` to the link; signers approve with that key or refuse, and the
131
+ * flow rejects approvals from any other key. Switching accounts takes a
132
+ * flow without it. Sign-up flows reject it.
133
+ */
134
+ expectedSigner?: string | null;
99
135
  }
100
136
 
101
137
  /**
@@ -152,7 +188,7 @@ export type GrantApprovalFormat = "bareGrant" | "signedApprovalV1";
152
188
  *
153
189
  * @property name - A machine-readable error code from {@link PubkyErrorName}. Use this for programmatic error handling.
154
190
  * @property message - A human-readable, descriptive error message suitable for logging.
155
- * @property data - An optional payload containing structured context for an error. For a `RequestError`, this may contain an object with the HTTP status code, e.g., `{ statusCode: 404 }`.
191
+ * @property data - Optional structured context. For a `RequestError` it is a {@link RequestErrorData}, e.g. `{ reason: "Http", statusCode: 404 }`.
156
192
  *
157
193
  * @example
158
194
  * ```typescript
@@ -160,14 +196,11 @@ export type GrantApprovalFormat = "bareGrant" | "signedApprovalV1";
160
196
  * await client.signup(...);
161
197
  * } catch (e) {
162
198
  * const error = e as PubkyError;
163
- * if (
164
- * error.name === "RequestError" &&
165
- * typeof error.data === "object" &&
166
- * error.data !== null &&
167
- * "statusCode" in error.data &&
168
- * (error.data as { statusCode?: number }).statusCode === 404
169
- * ) {
170
- * // Handle not found...
199
+ * if (error.name === "RequestError") {
200
+ * const data = error.data as RequestErrorData;
201
+ * if (data.statusCode === 404) {
202
+ * // Handle not found...
203
+ * }
171
204
  * }
172
205
  * }
173
206
  * ```
@@ -178,13 +211,35 @@ export interface PubkyError extends Error {
178
211
  data?: unknown;
179
212
  }
180
213
 
214
+ /** The classified cause of a `RequestError`, carried in `PubkyError.data.reason`. */
215
+ export type RequestErrorReason =
216
+ | "Http"
217
+ | "Timeout"
218
+ | "Connection"
219
+ | "TlsVerification"
220
+ | "Body"
221
+ | "Decode"
222
+ | "InvalidRequest"
223
+ | "Other";
224
+
225
+ /**
226
+ * `PubkyError.data` for a `RequestError`.
227
+ *
228
+ * `statusCode` is present when `reason` is `"Http"`. A reason describes the
229
+ * failure, not whether retrying is safe.
230
+ */
231
+ export interface RequestErrorData {
232
+ reason: RequestErrorReason;
233
+ statusCode?: number;
234
+ }
235
+
181
236
  /**
182
237
  * Represents the standard error structure for all exceptions thrown by the Pubky
183
238
  * WASM client.
184
239
  *
185
240
  * @property name - A machine-readable error code from {@link PubkyErrorName}. Use this for programmatic error handling.
186
241
  * @property message - A human-readable, descriptive error message suitable for logging.
187
- * @property data - An optional payload containing structured context for an error. For a `RequestError`, this may contain an object with the HTTP status code, e.g., `{ statusCode: 404 }`.
242
+ * @property data - Optional structured context. For a `RequestError` it is a {@link RequestErrorData}, e.g. `{ reason: "Http", statusCode: 404 }`.
188
243
  *
189
244
  * @example
190
245
  * ```typescript
@@ -192,14 +247,11 @@ export interface PubkyError extends Error {
192
247
  * await client.signup(...);
193
248
  * } catch (e) {
194
249
  * const error = e as PubkyError;
195
- * if (
196
- * error.name === 'RequestError' &&
197
- * typeof error.data === 'object' &&
198
- * error.data !== null &&
199
- * 'statusCode' in error.data &&
200
- * (error.data as { statusCode?: number }).statusCode === 404
201
- * ) {
202
- * // Handle not found...
250
+ * if (error.name === 'RequestError') {
251
+ * const data = error.data as RequestErrorData;
252
+ * if (data.statusCode === 404) {
253
+ * // Handle not found...
254
+ * }
203
255
  * }
204
256
  * }
205
257
  * ```
@@ -304,6 +356,39 @@ export type Capabilities = "" | CapabilityEntry | `${CapabilityEntry}${Capabilit
304
356
  export type Path = `/pub/${string}` | `/priv/${string}`;
305
357
 
306
358
 
359
+ /**
360
+ * A user's account as returned by `session.grant.account()`.
361
+ */
362
+ export class AccountInfo {
363
+ private constructor();
364
+ free(): void;
365
+ [Symbol.dispose](): void;
366
+ /**
367
+ * When the user signed up, as an ISO 8601 date and time without a UTC
368
+ * offset (e.g. `2026-10-22T10:11:12.123456`).
369
+ */
370
+ readonly createdAt: string;
371
+ /**
372
+ * Whether the account is disabled. Disabled accounts can read and delete
373
+ * but not write.
374
+ */
375
+ readonly disabled: boolean;
376
+ /**
377
+ * The user this account belongs to.
378
+ */
379
+ readonly pubky: PublicKey;
380
+ /**
381
+ * The quota that applies and the per-user overrides behind it.
382
+ *
383
+ * @returns {AccountQuota}
384
+ */
385
+ readonly quota: AccountQuota;
386
+ /**
387
+ * Bytes of storage currently used.
388
+ */
389
+ readonly usedBytes: number;
390
+ }
391
+
307
392
  /**
308
393
  * Start and control a pubkyauth authorization flow.
309
394
  *
@@ -1054,7 +1139,7 @@ export class GrantAuthFlow {
1054
1139
  * The kind of authentication flow to perform.
1055
1140
  *
1056
1141
  * @param {GrantAuthFlowOptions} options
1057
- * Options for the grant flow: `{ clientId, relay?, xCallback? }`.
1142
+ * Options for the grant flow: `{ clientId, relay?, xCallback?, approvalFormat?, expectedSigner? }`.
1058
1143
  *
1059
1144
  * @returns {GrantAuthFlow}
1060
1145
  * A running grant auth flow. Call `authorizationUrl()` to show the deep link,
@@ -1154,6 +1239,17 @@ export class GrantSession {
1154
1239
  private constructor();
1155
1240
  free(): void;
1156
1241
  [Symbol.dispose](): void;
1242
+ /**
1243
+ * Fetch this user's account: storage used, whether it is disabled, and
1244
+ * the quota that applies.
1245
+ *
1246
+ * Requires read permission on the root scope (`/:r`, `/:rw`, ...).
1247
+ * Path-scoped sessions surface the homeserver `403` as the standard
1248
+ * request error.
1249
+ *
1250
+ * @returns {Promise<AccountInfo>}
1251
+ */
1252
+ account(): Promise<AccountInfo>;
1157
1253
  /**
1158
1254
  * Sign JSON data and return both the custom proof and its root-signed grant.
1159
1255
  * Data follows `JSON.stringify` semantics, e.g. `undefined` properties are omitted.
@@ -1596,7 +1692,7 @@ export class Pubky {
1596
1692
  * @param {string} capabilities Comma-separated caps, e.g. `"/pub/app/:rw,/pub/foo/file:r"`.
1597
1693
  * @param {AuthFlowKind} kind The kind of authentication flow to perform.
1598
1694
  * @param {GrantAuthFlowOptions} options Options for the grant flow:
1599
- * `{ clientId, relay?, xCallback?, approvalFormat? }`.
1695
+ * `{ clientId, relay?, xCallback?, approvalFormat?, expectedSigner? }`.
1600
1696
  * @returns {Promise<GrantAuthFlow>}
1601
1697
  * A running grant auth flow. Show `authorizationUrl` as QR/deeplink,
1602
1698
  * then `awaitApproval()` to obtain a grant-backed `Session`.
@@ -1697,7 +1793,8 @@ export class PubkyResource {
1697
1793
  */
1698
1794
  static parse(value: string): PubkyResource;
1699
1795
  /**
1700
- * Render as `pubky://<owner>/<path>` (deep-link/URL form).
1796
+ * Render as `pubky://<owner><path>` (deep-link form), the form listings
1797
+ * and events use.
1701
1798
  */
1702
1799
  toPubkyUrl(): string;
1703
1800
  /**
@@ -1709,7 +1806,7 @@ export class PubkyResource {
1709
1806
  */
1710
1807
  readonly owner: PublicKey;
1711
1808
  /**
1712
- * Get the absolute path (e.g., "/pub/example.txt").
1809
+ * Get the absolute path (e.g., "/pub/My File.txt").
1713
1810
  */
1714
1811
  readonly path: string;
1715
1812
  }
@@ -1779,10 +1876,10 @@ export class PublicStorage {
1779
1876
  */
1780
1877
  get(address: Address): Promise<Response>;
1781
1878
  /**
1782
- * List a directory. Results are `pubky://…` identifier URLs.
1879
+ * List a directory. Results are `pubky://<pk><path>` entries.
1783
1880
  *
1784
1881
  * @param {Address} address Addressed directory (must end with `/`).
1785
- * @param {string|null=} cursor Optional suffix or full URL to start **after**.
1882
+ * @param {string|null=} cursor Optional suffix or entry (as returned) to start **after**.
1786
1883
  * @param {boolean=} reverse Default `false`. When `true`, newest/lexicographically-last first.
1787
1884
  * @param {number=} limit Optional result limit.
1788
1885
  * @param {boolean=} shallow Default `false`. When `true`, lists only first-level entries.
@@ -1937,8 +2034,10 @@ export class SessionInfo {
1937
2034
  *
1938
2035
  * Failures reject with a {@link PubkyError}. Path validation, transport, and HTTP
1939
2036
  * failures use `RequestError`; only HTTP errors include `data.statusCode`.
1940
- * URL parsing failures use `InvalidInput`. Credential preparation, refresh,
1941
- * and reading response bodies can also fail.
2037
+ * Automatic grant refresh failures use `CredentialRefreshError`, with the
2038
+ * refresh HTTP status in `data.statusCode` when available. URL parsing failures
2039
+ * use `InvalidInput`. Other credential preparation and reading response bodies
2040
+ * can also fail.
1942
2041
  *
1943
2042
  * Only {@link SessionStorage.exists} and {@link SessionStorage.stats} treat
1944
2043
  * HTTP 404/410 as missing. Other HTTP failures, including 401/403 and 5xx, reject.
@@ -2017,11 +2116,11 @@ export class SessionStorage {
2017
2116
  * List a directory (absolute session path).
2018
2117
  *
2019
2118
  * @param {Path} path Must end with `/`.
2020
- * @param {string|null=} cursor Optional last entry URL to start **after**.
2119
+ * @param {string|null=} cursor Optional last entry (as returned) to start **after**.
2021
2120
  * @param {boolean=} reverse Default `false`.
2022
2121
  * @param {number=} limit Optional result limit.
2023
2122
  * @param {boolean=} shallow Default `false`.
2024
- * @returns {Promise<string[]>} `pubky://…` entry URLs, or an empty array for an empty page.
2123
+ * @returns {Promise<string[]>} `pubky://<pk><path>` entries, or an empty array for an empty page.
2025
2124
  * @throws {PubkyError} Missing directory (404), invalid cursor (400), invalid response
2026
2125
  * entries, or shared errors (see {@link SessionStorage}).
2027
2126
  */
@@ -2044,6 +2143,38 @@ export class SessionStorage {
2044
2143
  * See {@link SessionStorage} for shared errors.
2045
2144
  */
2046
2145
  lock(path: Path, timeout_seconds: number): Promise<StorageLock>;
2146
+ /**
2147
+ * Upload a Blob or File to a locked path without copying its contents into
2148
+ * WASM memory.
2149
+ *
2150
+ * @param {StorageLock} lock A lock you hold. The upload uses the lock's path.
2151
+ * @param {Blob} body A Blob or File to upload.
2152
+ * @returns {Promise<void>}
2153
+ * @throws {PubkyError} An expired or released lock rejects with status `412`.
2154
+ * A file that changed since the write was prepared rejects with status `409`.
2155
+ * See {@link SessionStorage.putBytesLocked} for recovery and
2156
+ * {@link SessionStorage.putBlob} for input validation and shared errors.
2157
+ * @example
2158
+ * const lock = await session.storage.lock("/pub/example.com/file.bin", 30);
2159
+ * try {
2160
+ * await session.storage.putBlobLocked(lock, file);
2161
+ * } finally {
2162
+ * await session.storage.unlock(lock);
2163
+ * }
2164
+ */
2165
+ putBlobLocked(lock: StorageLock, body: Blob): Promise<void>;
2166
+ /**
2167
+ * Upload a Blob or File without copying its contents into WASM memory.
2168
+ *
2169
+ * @param {Path} path File path; must not end with `/`.
2170
+ * @param {Blob} body A Blob or File to upload.
2171
+ * @returns {Promise<void>}
2172
+ * @throws {PubkyError} `InvalidInput` if body is not a Blob or File;
2173
+ * otherwise upload or shared write/request errors (see {@link SessionStorage}).
2174
+ * @example
2175
+ * await session.storage.putBlob("/pub/example.com/file.bin", file);
2176
+ */
2177
+ putBlob(path: Path, body: Blob): Promise<void>;
2047
2178
  /**
2048
2179
  * `PUT` binary data to the path of a lock this client holds.
2049
2180
  *
@@ -2325,6 +2456,13 @@ export class SigninGrantDeepLink {
2325
2456
  * @returns {Uint8Array|undefined}
2326
2457
  */
2327
2458
  readonly ephemeralPublicKey: Uint8Array | undefined;
2459
+ /**
2460
+ * Expected identity (`spk`): the public key that must approve this
2461
+ * request, or `undefined`. Signers approve with this key or refuse.
2462
+ *
2463
+ * @returns {PublicKey|undefined}
2464
+ */
2465
+ readonly expectedSigner: PublicKey | undefined;
2328
2466
  /**
2329
2467
  * Shared relay secret, or `undefined` for an HPKE link.
2330
2468
  * Keep this secret confidential until the flow completes or is abandoned.
package/pubky_bg.wasm CHANGED
Binary file