@synonymdev/pubky 0.14.0 → 0.16.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/README.md +142 -5
- package/index.cjs +786 -177
- package/index.js +788 -178
- package/package.json +5 -3
- package/pubky.d.ts +348 -27
- package/pubky_bg.wasm +0 -0
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.
|
|
5
|
+
"version": "0.16.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -10,14 +10,15 @@
|
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"testnet": "cargo run -p pubky-testnet",
|
|
13
|
-
"build:test": "tsc --project tsconfig.json && mkdir -p dist && cp index.js dist/index.js",
|
|
13
|
+
"build:test": "rm -rf dist/tests && tsc --project tsconfig.json && mkdir -p dist && cp index.js dist/index.js",
|
|
14
14
|
"test": "npm run test-nodejs && npm run test-browser",
|
|
15
15
|
"test-nodejs": "npm run build:test && node --require ./node-header.cjs node_modules/tape/bin/tape dist/tests/*.js -cov",
|
|
16
16
|
"test-browser": "npm run build:test && browserify dist/tests/setup.js dist/tests/*.js -p esmify | npx tape-run",
|
|
17
17
|
"test-browser:ci": "npm run build:test && browserify dist/tests/setup.js dist/tests/*.js -p esmify | tape-run --browser electron --electron-arg=--no-sandbox --electron-arg=--disable-gpu",
|
|
18
18
|
"build": "cargo run --bin bundle_npm",
|
|
19
19
|
"docs": "typedoc",
|
|
20
|
-
"prepublishOnly": "npm run build"
|
|
20
|
+
"prepublishOnly": "npm run build",
|
|
21
|
+
"test-browser:tabs": "npm run build:test && browserify dist/tests/browser/session-tabs.js -p esmify -o dist/session-tabs.bundle.js && electron scripts/session-tabs.cjs"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
24
|
"index.cjs",
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"@types/tape": "^5.6.4",
|
|
41
42
|
"browser-resolve": "^2.0.0",
|
|
42
43
|
"browserify": "^17.0.1",
|
|
44
|
+
"electron": "41.0.2",
|
|
43
45
|
"esmify": "^2.1.1",
|
|
44
46
|
"tape": "^5.8.1",
|
|
45
47
|
"tape-run": "^11.0.0",
|
package/pubky.d.ts
CHANGED
|
@@ -12,6 +12,32 @@ export type Level = "error" | "warn" | "info" | "debug" | "trace";
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
export type ReadableStreamType = "bytes";
|
|
15
|
+
|
|
16
|
+
/** Offline recovery result. Check the identity before using the keys. */
|
|
17
|
+
export interface RecoveredEncryptionKeys {
|
|
18
|
+
/** Authenticated account public key, encoded as z-base-32. */
|
|
19
|
+
publicKey: string;
|
|
20
|
+
/** Authenticated grant identifier (jti). */
|
|
21
|
+
grantId: string;
|
|
22
|
+
/** Independently owned scoped keys. Call keys.free() when finished. */
|
|
23
|
+
keys: EncryptionKeys;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
|
|
29
|
+
/** Root-signed grant claims. Public keys are z-base-32; times are Unix seconds. */
|
|
30
|
+
export interface VerifiedGrantClaims {
|
|
31
|
+
iss: string;
|
|
32
|
+
client_id: string;
|
|
33
|
+
caps: string[];
|
|
34
|
+
cnf: string;
|
|
35
|
+
jti: string;
|
|
36
|
+
iat: number;
|
|
37
|
+
exp: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
15
41
|
/**
|
|
16
42
|
* A union type of all possible machine-readable codes for the `name` property
|
|
17
43
|
* of a {@link PubkyError}.
|
|
@@ -63,6 +89,25 @@ export interface GrantAuthFlowOptions {
|
|
|
63
89
|
* Optional return destinations for success, error, and cancellation.
|
|
64
90
|
*/
|
|
65
91
|
xCallback?: XCallbackParams | null;
|
|
92
|
+
/**
|
|
93
|
+
* Relay approval format. `signedApprovalV1` delivers keys for approved `e` scopes
|
|
94
|
+
* and rejects bare-grant downgrades.
|
|
95
|
+
* Omitted or `bareGrant` selects a grant without an approval envelope.
|
|
96
|
+
* `signedApprovalV1` sets `af=v1` in the authorization link.
|
|
97
|
+
*/
|
|
98
|
+
approvalFormat?: GrantApprovalFormat;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Options for verifying custom grant proofs.
|
|
103
|
+
*/
|
|
104
|
+
export interface CustomPopVerificationOptions {
|
|
105
|
+
/**
|
|
106
|
+
* Allow the grant's issue time this many seconds ahead of the local clock.
|
|
107
|
+
* Defaults to 30; zero disables the allowance. Expiry remains strict.
|
|
108
|
+
* Must be an integer between 0 and 4294967295.
|
|
109
|
+
*/
|
|
110
|
+
clockSkewSeconds?: number;
|
|
66
111
|
}
|
|
67
112
|
|
|
68
113
|
/**
|
|
@@ -74,8 +119,8 @@ export interface PkarrConfig {
|
|
|
74
119
|
*/
|
|
75
120
|
relays?: string[];
|
|
76
121
|
/**
|
|
77
|
-
* The timeout for
|
|
78
|
-
* Default is
|
|
122
|
+
* The timeout for relay HTTP requests in milliseconds.
|
|
123
|
+
* Default is 5000ms.
|
|
79
124
|
*/
|
|
80
125
|
requestTimeout?: number;
|
|
81
126
|
}
|
|
@@ -96,6 +141,11 @@ export interface PubkyClientConfig {
|
|
|
96
141
|
maxErrorBodyBytes?: number;
|
|
97
142
|
}
|
|
98
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Relay payload format understood by the requesting app.
|
|
146
|
+
*/
|
|
147
|
+
export type GrantApprovalFormat = "bareGrant" | "signedApprovalV1";
|
|
148
|
+
|
|
99
149
|
/**
|
|
100
150
|
* Represents the standard error structure for all exceptions thrown by the Pubky
|
|
101
151
|
* WASM client.
|
|
@@ -202,9 +252,50 @@ export interface ResourceStats {
|
|
|
202
252
|
etag?: string;
|
|
203
253
|
}
|
|
204
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Self-contained credentials for offline custom-proof verification.
|
|
257
|
+
* Unknown fields are ignored so future bundles remain readable by older verifiers.
|
|
258
|
+
*/
|
|
259
|
+
export interface CustomPop {
|
|
260
|
+
/**
|
|
261
|
+
* Original root-signed grant JWS.
|
|
262
|
+
*/
|
|
263
|
+
grant: string;
|
|
264
|
+
/**
|
|
265
|
+
* Client-signed custom proof JWS.
|
|
266
|
+
*/
|
|
267
|
+
pop: string;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Verified provenance and data; applications validate the data's meaning.
|
|
272
|
+
*/
|
|
273
|
+
export interface VerifiedCustomPop {
|
|
274
|
+
/**
|
|
275
|
+
* Root public key encoded as z-base-32.
|
|
276
|
+
*/
|
|
277
|
+
identity: string;
|
|
278
|
+
/**
|
|
279
|
+
* Root-signed claims; storage capabilities do not grant service permissions.
|
|
280
|
+
*/
|
|
281
|
+
grantClaims: VerifiedGrantClaims;
|
|
282
|
+
/**
|
|
283
|
+
* Unix seconds at which the client signed the proof. No maximum age is enforced.
|
|
284
|
+
*/
|
|
285
|
+
iat: number;
|
|
286
|
+
/**
|
|
287
|
+
* Random per-proof value. Record it until grant expiry to detect replays.
|
|
288
|
+
*/
|
|
289
|
+
nonce: string;
|
|
290
|
+
/**
|
|
291
|
+
* Signed JSON data, without application-specific validation.
|
|
292
|
+
*/
|
|
293
|
+
data: JsonValue;
|
|
294
|
+
}
|
|
295
|
+
|
|
205
296
|
export type Address = `pubky${string}/pub/${string}` | `pubky://${string}/pub/${string}`;
|
|
206
297
|
|
|
207
|
-
export type CapabilityAction = "r" | "w" | "rw";
|
|
298
|
+
export type CapabilityAction = "r" | "w" | "e" | "rw" | "re" | "we" | "rwe";
|
|
208
299
|
export type CapabilityScope = `/${string}`;
|
|
209
300
|
export type CapabilityEntry = `${CapabilityScope}:${CapabilityAction}`;
|
|
210
301
|
type CapabilitiesTail = `,${CapabilityEntry}${string}`;
|
|
@@ -459,7 +550,7 @@ export class BrowserSessionStore {
|
|
|
459
550
|
* This removes all stored session records and all browser-held delegated
|
|
460
551
|
* grant keys, including keys for pending delegated grant flows. Saved
|
|
461
552
|
* delegated flow state becomes unrestorable. This does not revoke remote
|
|
462
|
-
* grants
|
|
553
|
+
* grants. Browser-managed handles stop working when their saved record is removed.
|
|
463
554
|
*/
|
|
464
555
|
clearAll(): Promise<void>;
|
|
465
556
|
/**
|
|
@@ -470,7 +561,7 @@ export class BrowserSessionStore {
|
|
|
470
561
|
*/
|
|
471
562
|
clear(): Promise<void>;
|
|
472
563
|
/**
|
|
473
|
-
* Whether IndexedDB
|
|
564
|
+
* Whether IndexedDB and Web Locks are available.
|
|
474
565
|
*/
|
|
475
566
|
isAvailable(): Promise<boolean>;
|
|
476
567
|
/**
|
|
@@ -481,12 +572,29 @@ export class BrowserSessionStore {
|
|
|
481
572
|
* Remove local stored session metadata and any SDK-owned delegated key for that record.
|
|
482
573
|
*/
|
|
483
574
|
remove(id: string): Promise<void>;
|
|
575
|
+
/**
|
|
576
|
+
* Recover a stored session's encryption keys without network access.
|
|
577
|
+
* Verifies the signed approval, exact grant binding, and requested session
|
|
578
|
+
* identity. Works after grant expiry/revocation and without the delegated
|
|
579
|
+
* WebCrypto signing key.
|
|
580
|
+
* Restore material is stored as plaintext in IndexedDB.
|
|
581
|
+
* Bare-grant records return undefined; signed approvals without `e` scopes
|
|
582
|
+
* return an empty bundle. Creates no session.
|
|
583
|
+
*/
|
|
584
|
+
restoreEncryptionKeys(id: string): Promise<EncryptionKeys | undefined>;
|
|
484
585
|
/**
|
|
485
586
|
* Restore a specific stored session by id.
|
|
587
|
+
*
|
|
588
|
+
* Shares one bearer with other tabs on this origin. Requires IndexedDB and
|
|
589
|
+
* Web Locks in a secure browser context.
|
|
486
590
|
*/
|
|
487
591
|
restore(id: string): Promise<Session>;
|
|
488
592
|
/**
|
|
489
|
-
* Persist a completed grant session
|
|
593
|
+
* Persist a completed grant session and its optional signed approval.
|
|
594
|
+
* Confidential restore material is stored as plaintext in IndexedDB.
|
|
595
|
+
* Delegated signing keys remain non-extractable WebCrypto keys.
|
|
596
|
+
* Records are identified by user and grant ID. Reauthorizing the same
|
|
597
|
+
* client creates a separate record; use the returned ID to restore it.
|
|
490
598
|
*/
|
|
491
599
|
save(session: Session): Promise<StoredSessionInfo>;
|
|
492
600
|
}
|
|
@@ -614,6 +722,42 @@ export class DirectSignupDeepLink {
|
|
|
614
722
|
readonly xCallback: XCallbackParams;
|
|
615
723
|
}
|
|
616
724
|
|
|
725
|
+
/**
|
|
726
|
+
* Verified scoped encryption keys obtained from a session or offline recovery.
|
|
727
|
+
* This object owns its secrets independently of the session and grants no storage
|
|
728
|
+
* access. Call `free()` when finished; secret bytes are zeroized on free/drop.
|
|
729
|
+
*/
|
|
730
|
+
export class EncryptionKeys {
|
|
731
|
+
private constructor();
|
|
732
|
+
free(): void;
|
|
733
|
+
[Symbol.dispose](): void;
|
|
734
|
+
/**
|
|
735
|
+
* Derive a non-extractable AES-GCM-256 key for WebCrypto encryption/decryption.
|
|
736
|
+
* Rejects directories and files outside approved scopes. Requires WebCrypto.
|
|
737
|
+
* Temporary JS key bytes are cleared after import, including on failure.
|
|
738
|
+
*/
|
|
739
|
+
deriveCryptoKeyForPath(path: string): Promise<CryptoKey>;
|
|
740
|
+
/**
|
|
741
|
+
* Derive a 32-byte content key for a canonical decoded file path.
|
|
742
|
+
* Rejects directories and files outside the approved scopes. The caller
|
|
743
|
+
* owns the JS byte copy and should clear it after use.
|
|
744
|
+
*/
|
|
745
|
+
deriveForPath(path: string): Uint8Array;
|
|
746
|
+
/**
|
|
747
|
+
* Recover authenticated identity and keys from an exportLocalSecret() token offline.
|
|
748
|
+
* Verifies the signed approval and grant binding even if the grant expired
|
|
749
|
+
* or was revoked. Bare-grant tokens return undefined; signed approvals
|
|
750
|
+
* without `e` scopes return a result with an empty key bundle.
|
|
751
|
+
* Check publicKey (z-base-32) against the expected account and grantId
|
|
752
|
+
* against the expected grant before using keys. Call keys.free() when done.
|
|
753
|
+
*/
|
|
754
|
+
static fromLocalSecret(token: string): RecoveredEncryptionKeys | undefined;
|
|
755
|
+
/**
|
|
756
|
+
* Approved scopes; directory scopes cover descendant files.
|
|
757
|
+
*/
|
|
758
|
+
readonly scopes: string[];
|
|
759
|
+
}
|
|
760
|
+
|
|
617
761
|
/**
|
|
618
762
|
* A single event from the event stream.
|
|
619
763
|
*
|
|
@@ -864,7 +1008,8 @@ export class GrantAuthFlow {
|
|
|
864
1008
|
* Resume a previously saved pending grant auth flow (standalone).
|
|
865
1009
|
* Prefer `pubky.resumeGrantAuthFlow()` to reuse a facade client.
|
|
866
1010
|
*
|
|
867
|
-
* **Security:** `savedState` contains the
|
|
1011
|
+
* **Security:** `savedState` contains the PoP client private key and either
|
|
1012
|
+
* a shared relay secret or a temporary HPKE recipient secret.
|
|
868
1013
|
* Store it only temporarily and delete it once the flow completes or is abandoned.
|
|
869
1014
|
*
|
|
870
1015
|
* @param {string} savedState A string produced by `grantFlow.saveLocal()`.
|
|
@@ -874,9 +1019,9 @@ export class GrantAuthFlow {
|
|
|
874
1019
|
/**
|
|
875
1020
|
* Save sensitive state required to resume this delegated pending grant flow.
|
|
876
1021
|
*
|
|
877
|
-
* This
|
|
878
|
-
* secret
|
|
879
|
-
*
|
|
1022
|
+
* This includes either a shared relay secret or a temporary HPKE recipient
|
|
1023
|
+
* secret. Store it only temporarily and delete it once the flow completes
|
|
1024
|
+
* or is abandoned.
|
|
880
1025
|
*/
|
|
881
1026
|
saveDelegated(): string;
|
|
882
1027
|
/**
|
|
@@ -1009,11 +1154,19 @@ export class GrantSession {
|
|
|
1009
1154
|
private constructor();
|
|
1010
1155
|
free(): void;
|
|
1011
1156
|
[Symbol.dispose](): void;
|
|
1157
|
+
/**
|
|
1158
|
+
* Sign JSON data and return both the custom proof and its root-signed grant.
|
|
1159
|
+
* Data follows `JSON.stringify` semantics, e.g. `undefined` properties are omitted.
|
|
1160
|
+
* Each proof carries its signing time (`iat`) and a random `nonce`.
|
|
1161
|
+
* Makes no network requests. Your applications handle freshness and replay protection.
|
|
1162
|
+
*/
|
|
1163
|
+
createCustomPop(data: JsonValue): Promise<CustomPop>;
|
|
1012
1164
|
/**
|
|
1013
1165
|
* Export the portable local secret material needed to restore this grant session.
|
|
1014
1166
|
*
|
|
1015
1167
|
* Treat the returned string as bearer-equivalent secret material until the
|
|
1016
|
-
* grant expires or is revoked.
|
|
1168
|
+
* grant expires or is revoked. Included scoped keys remain sensitive after
|
|
1169
|
+
* expiry or revocation.
|
|
1017
1170
|
*
|
|
1018
1171
|
* @returns {Promise<string>}
|
|
1019
1172
|
*/
|
|
@@ -1030,6 +1183,15 @@ export class GrantSession {
|
|
|
1030
1183
|
* @returns {Promise<GrantSessionInfo>}
|
|
1031
1184
|
*/
|
|
1032
1185
|
sessionInfo(): Promise<GrantSessionInfo>;
|
|
1186
|
+
/**
|
|
1187
|
+
* Return scoped keys with the same derivation API as offline recovered keys.
|
|
1188
|
+
* Bare grants return `undefined`; signed approvals without `e` scopes
|
|
1189
|
+
* return an object with empty scopes.
|
|
1190
|
+
* Each access creates an owned copy. Keep it for repeated use and call
|
|
1191
|
+
* `free()` when finished. It remains usable after this view or its session
|
|
1192
|
+
* is freed, signed out, or revoked; freeing it does not affect the session.
|
|
1193
|
+
*/
|
|
1194
|
+
readonly encryptionKeys: EncryptionKeys | undefined;
|
|
1033
1195
|
}
|
|
1034
1196
|
|
|
1035
1197
|
/**
|
|
@@ -1367,8 +1529,9 @@ export class Pubky {
|
|
|
1367
1529
|
/**
|
|
1368
1530
|
* Resume a previously saved pending grant auth flow.
|
|
1369
1531
|
*
|
|
1370
|
-
* **Security:** `savedState` contains the
|
|
1371
|
-
*
|
|
1532
|
+
* **Security:** `savedState` contains the PoP client private key and either
|
|
1533
|
+
* a shared relay secret or a temporary HPKE private key. Delete it from
|
|
1534
|
+
* storage when the flow completes or is abandoned.
|
|
1372
1535
|
*
|
|
1373
1536
|
* @param {string} savedState A string produced by `grantFlow.saveLocal()`.
|
|
1374
1537
|
* @returns {GrantAuthFlow} A flow reconnected to the original relay channel.
|
|
@@ -1427,11 +1590,13 @@ export class Pubky {
|
|
|
1427
1590
|
*
|
|
1428
1591
|
* Grant auth uses a user-signed grant JWS plus Proof-of-Possession and
|
|
1429
1592
|
* returns a self-refreshing session.
|
|
1593
|
+
* Select `approvalFormat: "signedApprovalV1"` and include `e` on scopes that need content
|
|
1594
|
+
* keys. Storage `r` and `w` alone do not deliver encryption keys.
|
|
1430
1595
|
*
|
|
1431
1596
|
* @param {string} capabilities Comma-separated caps, e.g. `"/pub/app/:rw,/pub/foo/file:r"`.
|
|
1432
1597
|
* @param {AuthFlowKind} kind The kind of authentication flow to perform.
|
|
1433
1598
|
* @param {GrantAuthFlowOptions} options Options for the grant flow:
|
|
1434
|
-
* `{ clientId, relay?, xCallback? }`.
|
|
1599
|
+
* `{ clientId, relay?, xCallback?, approvalFormat? }`.
|
|
1435
1600
|
* @returns {Promise<GrantAuthFlow>}
|
|
1436
1601
|
* A running grant auth flow. Show `authorizationUrl` as QR/deeplink,
|
|
1437
1602
|
* then `awaitApproval()` to obtain a grant-backed `Session`.
|
|
@@ -1778,12 +1943,23 @@ export class SessionInfo {
|
|
|
1778
1943
|
* Only {@link SessionStorage.exists} and {@link SessionStorage.stats} treat
|
|
1779
1944
|
* HTTP 404/410 as missing. Other HTTP failures, including 401/403 and 5xx, reject.
|
|
1780
1945
|
* Writes require write permission and can fail on directory targets (400),
|
|
1781
|
-
* file/directory path conflicts (409),
|
|
1946
|
+
* file/directory path conflicts (409), a path someone holds a
|
|
1947
|
+
* {@link StorageLock} on (423), or exceeded quotas (507).
|
|
1782
1948
|
*/
|
|
1783
1949
|
export class SessionStorage {
|
|
1784
1950
|
private constructor();
|
|
1785
1951
|
free(): void;
|
|
1786
1952
|
[Symbol.dispose](): void;
|
|
1953
|
+
/**
|
|
1954
|
+
* `DELETE` the path of a lock this client holds. The lock stays in place.
|
|
1955
|
+
*
|
|
1956
|
+
* @param {StorageLock} lock A lock this client holds.
|
|
1957
|
+
* @returns {Promise<void>}
|
|
1958
|
+
* @throws {PubkyError} A lock that has expired or was unlocked rejects with
|
|
1959
|
+
* `RequestError` and status `412`; take a new one.
|
|
1960
|
+
* Otherwise as {@link SessionStorage.delete}.
|
|
1961
|
+
*/
|
|
1962
|
+
deleteLocked(lock: StorageLock): Promise<void>;
|
|
1787
1963
|
/**
|
|
1788
1964
|
* Delete a file. Directory targets are unsupported.
|
|
1789
1965
|
*
|
|
@@ -1850,6 +2026,35 @@ export class SessionStorage {
|
|
|
1850
2026
|
* entries, or shared errors (see {@link SessionStorage}).
|
|
1851
2027
|
*/
|
|
1852
2028
|
list(path: Path, cursor?: string | null, reverse?: boolean | null, limit?: number | null, shallow?: boolean | null): Promise<string[]>;
|
|
2029
|
+
/**
|
|
2030
|
+
* Take an exclusive write lock on a file at an **absolute session path**.
|
|
2031
|
+
*
|
|
2032
|
+
* The file need not exist; locking a free path reserves it. `timeoutSeconds` is
|
|
2033
|
+
* the lifetime asked for; the homeserver caps it, and
|
|
2034
|
+
* {@link StorageLock.timeoutSeconds} tells what was granted. A write made under
|
|
2035
|
+
* the lock keeps it alive until the write ends, so it need not cover the upload itself.
|
|
2036
|
+
*
|
|
2037
|
+
* @param {Path} path File path; must not end with `/`.
|
|
2038
|
+
* @param {number} timeoutSeconds Lifetime to ask for, in seconds; rounded down to
|
|
2039
|
+
* whole seconds, and at least 1.
|
|
2040
|
+
* @returns {Promise<StorageLock>} The granted lock.
|
|
2041
|
+
* @throws {PubkyError} `InvalidInput` for a negative, NaN or out-of-range timeout;
|
|
2042
|
+
* a path that is already locked rejects with `RequestError` and status `423`;
|
|
2043
|
+
* directory targets with `400`; a homeserver without lock support with `405`.
|
|
2044
|
+
* See {@link SessionStorage} for shared errors.
|
|
2045
|
+
*/
|
|
2046
|
+
lock(path: Path, timeout_seconds: number): Promise<StorageLock>;
|
|
2047
|
+
/**
|
|
2048
|
+
* `PUT` binary data to the path of a lock this client holds.
|
|
2049
|
+
*
|
|
2050
|
+
* @param {StorageLock} lock A lock this client holds.
|
|
2051
|
+
* @param {Uint8Array} body
|
|
2052
|
+
* @returns {Promise<void>}
|
|
2053
|
+
* @throws {PubkyError} A lock that has expired or was unlocked rejects with
|
|
2054
|
+
* `RequestError` and status `412`; take a new one and read the file again.
|
|
2055
|
+
* Otherwise as {@link SessionStorage.putBytes}.
|
|
2056
|
+
*/
|
|
2057
|
+
putBytesLocked(lock: StorageLock, body: Uint8Array): Promise<void>;
|
|
1853
2058
|
/**
|
|
1854
2059
|
* Create or replace a file with binary data at an absolute session path.
|
|
1855
2060
|
*
|
|
@@ -1869,6 +2074,17 @@ export class SessionStorage {
|
|
|
1869
2074
|
* otherwise serialization, upload, or shared write/request errors (see {@link SessionStorage}).
|
|
1870
2075
|
*/
|
|
1871
2076
|
putJson(path: Path, body: any): Promise<void>;
|
|
2077
|
+
/**
|
|
2078
|
+
* `PUT` text to the path of a lock this client holds.
|
|
2079
|
+
*
|
|
2080
|
+
* @param {StorageLock} lock A lock this client holds.
|
|
2081
|
+
* @param {string} body
|
|
2082
|
+
* @returns {Promise<void>}
|
|
2083
|
+
* @throws {PubkyError} A lock that has expired or was unlocked rejects with
|
|
2084
|
+
* `RequestError` and status `412`; take a new one and read the file again.
|
|
2085
|
+
* Otherwise as {@link SessionStorage.putText}.
|
|
2086
|
+
*/
|
|
2087
|
+
putTextLocked(lock: StorageLock, body: string): Promise<void>;
|
|
1872
2088
|
/**
|
|
1873
2089
|
* Create or replace a file with text at an absolute session path.
|
|
1874
2090
|
*
|
|
@@ -1878,6 +2094,22 @@ export class SessionStorage {
|
|
|
1878
2094
|
* @throws {PubkyError} Upload or shared write/request errors (see {@link SessionStorage}).
|
|
1879
2095
|
*/
|
|
1880
2096
|
putText(path: Path, body: string): Promise<void>;
|
|
2097
|
+
/**
|
|
2098
|
+
* Restart the lifetime of a lock this client holds.
|
|
2099
|
+
*
|
|
2100
|
+
* On success the lock carries the newly granted
|
|
2101
|
+
* {@link StorageLock.timeoutSeconds}.
|
|
2102
|
+
*
|
|
2103
|
+
* @param {StorageLock} lock A lock this client holds.
|
|
2104
|
+
* @param {number} timeoutSeconds Lifetime to ask for, in seconds; rounded down to
|
|
2105
|
+
* whole seconds, and at least 1.
|
|
2106
|
+
* @returns {Promise<void>}
|
|
2107
|
+
* @throws {PubkyError} A lock that has expired or was unlocked rejects with
|
|
2108
|
+
* `RequestError` and status `412`; take a new one and read the file again.
|
|
2109
|
+
* `InvalidInput` for a negative, NaN or out-of-range timeout.
|
|
2110
|
+
* See {@link SessionStorage} for shared errors.
|
|
2111
|
+
*/
|
|
2112
|
+
refreshLock(lock: StorageLock, timeout_seconds: number): Promise<void>;
|
|
1881
2113
|
/**
|
|
1882
2114
|
* Get metadata for an absolute, session-scoped path (e.g. `"/pub/app/file.json"`).
|
|
1883
2115
|
*
|
|
@@ -1888,6 +2120,15 @@ export class SessionStorage {
|
|
|
1888
2120
|
* @throws {PubkyError} All other failures (see {@link SessionStorage}).
|
|
1889
2121
|
*/
|
|
1890
2122
|
stats(path: Path): Promise<ResourceStats | undefined>;
|
|
2123
|
+
/**
|
|
2124
|
+
* Release a lock this client holds.
|
|
2125
|
+
*
|
|
2126
|
+
* @param {StorageLock} lock A lock this client holds.
|
|
2127
|
+
* @returns {Promise<void>}
|
|
2128
|
+
* @throws {PubkyError} A lock that no longer exists rejects with `RequestError`
|
|
2129
|
+
* and status `409`. See {@link SessionStorage} for shared errors.
|
|
2130
|
+
*/
|
|
2131
|
+
unlock(lock: StorageLock): Promise<void>;
|
|
1891
2132
|
}
|
|
1892
2133
|
|
|
1893
2134
|
/**
|
|
@@ -1922,7 +2163,8 @@ export class Signer {
|
|
|
1922
2163
|
/**
|
|
1923
2164
|
* Blocking sign-in. Waits for PKDNS publish to complete (slower; safer).
|
|
1924
2165
|
*
|
|
1925
|
-
* Creates a
|
|
2166
|
+
* Creates a grant-backed homeserver session with root storage access (`/:rw`).
|
|
2167
|
+
* Encryption keys require an explicit `e` request through a signed approval flow.
|
|
1926
2168
|
* `clientId` is shown in the user's grant/session list.
|
|
1927
2169
|
* @param {string} clientId App identifier, typically a domain.
|
|
1928
2170
|
*
|
|
@@ -1944,7 +2186,8 @@ export class Signer {
|
|
|
1944
2186
|
/**
|
|
1945
2187
|
* Fast sign-in for a returning user. Publishes PKDNS in the background.
|
|
1946
2188
|
*
|
|
1947
|
-
* Creates a
|
|
2189
|
+
* Creates a grant-backed homeserver session with root storage access (`/:rw`).
|
|
2190
|
+
* Encryption keys require an explicit `e` request through a signed approval flow.
|
|
1948
2191
|
* `clientId` is shown in the user's grant/session list.
|
|
1949
2192
|
* @param {string} clientId App identifier, typically a domain.
|
|
1950
2193
|
*
|
|
@@ -2029,6 +2272,10 @@ export class SigninGrantDeepLink {
|
|
|
2029
2272
|
* @returns {string}
|
|
2030
2273
|
*/
|
|
2031
2274
|
toString(): string;
|
|
2275
|
+
/**
|
|
2276
|
+
* Negotiated approval format: `bareGrant` or `signedApprovalV1`.
|
|
2277
|
+
*/
|
|
2278
|
+
readonly approvalFormat: string;
|
|
2032
2279
|
/**
|
|
2033
2280
|
* Base HTTP relay inbox URL used by this auth request.
|
|
2034
2281
|
*
|
|
@@ -2054,13 +2301,21 @@ export class SigninGrantDeepLink {
|
|
|
2054
2301
|
*/
|
|
2055
2302
|
readonly clientPublicKey: PublicKey;
|
|
2056
2303
|
/**
|
|
2057
|
-
*
|
|
2304
|
+
* The 32-byte ephemeral HPKE public key from `epk`, or `undefined`
|
|
2305
|
+
* for a shared-secret link. The relay channel ID is the unpadded
|
|
2306
|
+
* base64url encoding of BLAKE3("pubky-grant-relay-channel-v1" || 0x00 || epk),
|
|
2307
|
+
* where `||` concatenates bytes and `epk` is the raw 32-byte public key.
|
|
2058
2308
|
*
|
|
2059
|
-
*
|
|
2309
|
+
* @returns {Uint8Array|undefined}
|
|
2310
|
+
*/
|
|
2311
|
+
readonly ephemeralPublicKey: Uint8Array | undefined;
|
|
2312
|
+
/**
|
|
2313
|
+
* Shared relay secret, or `undefined` for an HPKE link.
|
|
2314
|
+
* Keep this secret confidential until the flow completes or is abandoned.
|
|
2060
2315
|
*
|
|
2061
|
-
* @returns {Uint8Array}
|
|
2316
|
+
* @returns {Uint8Array|undefined}
|
|
2062
2317
|
*/
|
|
2063
|
-
readonly secret: Uint8Array;
|
|
2318
|
+
readonly secret: Uint8Array | undefined;
|
|
2064
2319
|
/**
|
|
2065
2320
|
* Optional x-callback-url metadata carried by this deep link.
|
|
2066
2321
|
*/
|
|
@@ -2108,6 +2363,10 @@ export class SignupGrantDeepLink {
|
|
|
2108
2363
|
* @returns {string}
|
|
2109
2364
|
*/
|
|
2110
2365
|
toString(): string;
|
|
2366
|
+
/**
|
|
2367
|
+
* Negotiated approval format: `bareGrant` or `signedApprovalV1`.
|
|
2368
|
+
*/
|
|
2369
|
+
readonly approvalFormat: string;
|
|
2111
2370
|
/**
|
|
2112
2371
|
* Base HTTP relay inbox URL used by this auth request.
|
|
2113
2372
|
*
|
|
@@ -2132,6 +2391,15 @@ export class SignupGrantDeepLink {
|
|
|
2132
2391
|
* @returns {PublicKey}
|
|
2133
2392
|
*/
|
|
2134
2393
|
readonly clientPublicKey: PublicKey;
|
|
2394
|
+
/**
|
|
2395
|
+
* The 32-byte ephemeral HPKE public key from `epk`, or `undefined`
|
|
2396
|
+
* for a shared-secret link. The relay channel ID is the unpadded
|
|
2397
|
+
* base64url encoding of BLAKE3("pubky-grant-relay-channel-v1" || 0x00 || epk),
|
|
2398
|
+
* where `||` concatenates bytes and `epk` is the raw 32-byte public key.
|
|
2399
|
+
*
|
|
2400
|
+
* @returns {Uint8Array|undefined}
|
|
2401
|
+
*/
|
|
2402
|
+
readonly ephemeralPublicKey: Uint8Array | undefined;
|
|
2135
2403
|
/**
|
|
2136
2404
|
* Homeserver public key requested for account creation.
|
|
2137
2405
|
*
|
|
@@ -2139,13 +2407,12 @@ export class SignupGrantDeepLink {
|
|
|
2139
2407
|
*/
|
|
2140
2408
|
readonly homeserver: PublicKey;
|
|
2141
2409
|
/**
|
|
2142
|
-
*
|
|
2143
|
-
*
|
|
2144
|
-
* Treat this as sensitive temporary auth-flow material.
|
|
2410
|
+
* Shared relay secret, or `undefined` for an HPKE link.
|
|
2411
|
+
* Keep this secret confidential until the flow completes or is abandoned.
|
|
2145
2412
|
*
|
|
2146
|
-
* @returns {Uint8Array}
|
|
2413
|
+
* @returns {Uint8Array|undefined}
|
|
2147
2414
|
*/
|
|
2148
|
-
readonly secret: Uint8Array;
|
|
2415
|
+
readonly secret: Uint8Array | undefined;
|
|
2149
2416
|
/**
|
|
2150
2417
|
* Optional signup token included in the request.
|
|
2151
2418
|
*
|
|
@@ -2158,6 +2425,52 @@ export class SignupGrantDeepLink {
|
|
|
2158
2425
|
readonly xCallback: XCallbackParams;
|
|
2159
2426
|
}
|
|
2160
2427
|
|
|
2428
|
+
/**
|
|
2429
|
+
* An exclusive write lock on one file path, granted by the homeserver.
|
|
2430
|
+
*
|
|
2431
|
+
* While the lock lives, only writes that present it are accepted on the path;
|
|
2432
|
+
* every other write, and every other {@link SessionStorage.lock}, rejects with
|
|
2433
|
+
* `423 Locked`. The lock ends when it is {@link SessionStorage.unlock | unlocked}
|
|
2434
|
+
* or when its {@link StorageLock.timeoutSeconds} runs out without a
|
|
2435
|
+
* {@link SessionStorage.refreshLock | refresh}, so a client that disappears never
|
|
2436
|
+
* blocks a path for long.
|
|
2437
|
+
*
|
|
2438
|
+
* The lock is a bearer token: whoever holds this value, and may write the path,
|
|
2439
|
+
* can use and release the lock.
|
|
2440
|
+
*
|
|
2441
|
+
* Calls that take the lock may overlap: a {@link SessionStorage.refreshLock | refresh}
|
|
2442
|
+
* can run while a locked write is in flight.
|
|
2443
|
+
*
|
|
2444
|
+
* @example
|
|
2445
|
+
* const lock = await session.storage.lock("/pub/my.app/state.json", 30);
|
|
2446
|
+
* const state = await session.storage.getText(lock.path);
|
|
2447
|
+
* await session.storage.putTextLocked(lock, state);
|
|
2448
|
+
* await session.storage.unlock(lock);
|
|
2449
|
+
*/
|
|
2450
|
+
export class StorageLock {
|
|
2451
|
+
private constructor();
|
|
2452
|
+
free(): void;
|
|
2453
|
+
[Symbol.dispose](): void;
|
|
2454
|
+
/**
|
|
2455
|
+
* Value of the `If` header that presents this lock on a write.
|
|
2456
|
+
*/
|
|
2457
|
+
ifHeader(): string;
|
|
2458
|
+
/**
|
|
2459
|
+
* The locked path.
|
|
2460
|
+
*/
|
|
2461
|
+
readonly path: Path;
|
|
2462
|
+
/**
|
|
2463
|
+
* Lifetime the homeserver granted at the last `lock` or `refreshLock`, in seconds,
|
|
2464
|
+
* counted from when that call resolved. It may be shorter than what was asked for.
|
|
2465
|
+
* It is not the time remaining: note when the call resolved to know when to refresh.
|
|
2466
|
+
*/
|
|
2467
|
+
readonly timeoutSeconds: number;
|
|
2468
|
+
/**
|
|
2469
|
+
* The lock token URL, `opaquelocktoken:<uuid>`.
|
|
2470
|
+
*/
|
|
2471
|
+
readonly token: string;
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2161
2474
|
/**
|
|
2162
2475
|
* Metadata for a session saved in the browser session store.
|
|
2163
2476
|
*/
|
|
@@ -2237,7 +2550,8 @@ export function setLogLevel(level: Level): void;
|
|
|
2237
2550
|
/**
|
|
2238
2551
|
* Validate and normalize a capabilities string.
|
|
2239
2552
|
*
|
|
2240
|
-
* - Normalizes action order (`wr` -> `rw`)
|
|
2553
|
+
* - Normalizes action order (`wr` -> `rw`, `ewr` -> `rwe`).
|
|
2554
|
+
* - `e` requests scoped encryption/decryption keys in V1 grant approvals.
|
|
2241
2555
|
* - Throws `InvalidInput` identifying the first malformed entry.
|
|
2242
2556
|
*
|
|
2243
2557
|
* @param {string} input
|
|
@@ -2246,3 +2560,10 @@ export function setLogLevel(level: Level): void;
|
|
|
2246
2560
|
* The error's `data` field is `{ invalidEntries: string[] }` containing the malformed token.
|
|
2247
2561
|
*/
|
|
2248
2562
|
export function validateCapabilities(input: string): string;
|
|
2563
|
+
|
|
2564
|
+
/**
|
|
2565
|
+
* Verify both signatures, grant binding, and grant validity against the local clock.
|
|
2566
|
+
* Allows 30 seconds of future clock skew by default; never extends grant expiry.
|
|
2567
|
+
* Does not check replay, application authorization, or homeserver revocation.
|
|
2568
|
+
*/
|
|
2569
|
+
export function verifyCustomGrantPop(credentials: CustomPop, options?: CustomPopVerificationOptions | null): VerifiedCustomPop;
|
package/pubky_bg.wasm
CHANGED
|
Binary file
|