@tinycloud/node-sdk 3.8.0-beta.0 → 3.8.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{TinyCloudNode-BtKzLDJX.d.ts → TinyCloudNode-B6VOBrCb.d.ts} +15 -2
- package/dist/{TinyCloudNode-ggmlnSfI.d.cts → TinyCloudNode-CVO41O12.d.cts} +15 -2
- package/dist/{authority-sJ6buHMj.d.ts → authority-DGi1hIMK.d.ts} +21 -5
- package/dist/{authority-_SYAE-uV.d.cts → authority-DgVV80bI.d.cts} +21 -5
- package/dist/core.cjs +54 -17
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +3 -3
- package/dist/core.d.ts +3 -3
- package/dist/core.js +54 -17
- package/dist/core.js.map +1 -1
- package/dist/encryption-keys.d.cts +1 -1
- package/dist/encryption-keys.d.ts +1 -1
- package/dist/index.cjs +93 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +93 -18
- package/dist/index.js.map +1 -1
- package/dist/replication/authority.cjs +40 -1
- package/dist/replication/authority.cjs.map +1 -1
- package/dist/replication/authority.d.cts +2 -2
- package/dist/replication/authority.d.ts +2 -2
- package/dist/replication/authority.js +39 -1
- package/dist/replication/authority.js.map +1 -1
- package/dist/replication/runtime.cjs.map +1 -1
- package/dist/replication/runtime.d.cts +1 -1
- package/dist/replication/runtime.d.ts +1 -1
- package/dist/replication/runtime.js.map +1 -1
- package/dist/{runtime-v62FzQHz.d.ts → runtime-CO4VXnPq.d.ts} +2 -1
- package/dist/{runtime-D1o9Eybt.d.cts → runtime-mRhSu-vJ.d.cts} +2 -1
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NamedKeyClient } from '@tinycloud/sdk-services/encryption/named-keys';
|
|
2
2
|
export { DecryptManyResult, KeyCallOptions, KeyDescriptor, KeyEncryptOptions, NamedKeyClient, NamedKeyEnvelope, NamedKeyError, NamedKeyErrorCode, PublicKeyDescriptor, buildKeyAdminFacts, buildKeyDescribeFacts } from '@tinycloud/sdk-services/encryption/named-keys';
|
|
3
|
-
import { T as TinyCloudNode } from './TinyCloudNode-
|
|
3
|
+
import { T as TinyCloudNode } from './TinyCloudNode-CVO41O12.cjs';
|
|
4
4
|
import '@tinycloud/sdk-core';
|
|
5
5
|
import '@tinycloud/sdk-services/kv/replication';
|
|
6
6
|
import '@tinycloud/sdk-services';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NamedKeyClient } from '@tinycloud/sdk-services/encryption/named-keys';
|
|
2
2
|
export { DecryptManyResult, KeyCallOptions, KeyDescriptor, KeyEncryptOptions, NamedKeyClient, NamedKeyEnvelope, NamedKeyError, NamedKeyErrorCode, PublicKeyDescriptor, buildKeyAdminFacts, buildKeyDescribeFacts } from '@tinycloud/sdk-services/encryption/named-keys';
|
|
3
|
-
import { T as TinyCloudNode } from './TinyCloudNode-
|
|
3
|
+
import { T as TinyCloudNode } from './TinyCloudNode-B6VOBrCb.js';
|
|
4
4
|
import '@tinycloud/sdk-core';
|
|
5
5
|
import '@tinycloud/sdk-services/kv/replication';
|
|
6
6
|
import '@tinycloud/sdk-services';
|
package/dist/index.cjs
CHANGED
|
@@ -17053,7 +17053,7 @@ function augmentSignInEntriesWithReplication(input) {
|
|
|
17053
17053
|
}
|
|
17054
17054
|
eligiblePaths.push(path);
|
|
17055
17055
|
}
|
|
17056
|
-
if (eligiblePaths.length === replication.prefixes.length && eligiblePaths.length > 0 && hasUnrestrictedGetCoverage(input.entries, input.primarySpaceId, "")) {
|
|
17056
|
+
if (replication.syncScope !== "prefixes" && eligiblePaths.length === replication.prefixes.length && eligiblePaths.length > 0 && hasUnrestrictedGetCoverage(input.entries, input.primarySpaceId, "")) {
|
|
17057
17057
|
return [{
|
|
17058
17058
|
service: KV_SERVICE,
|
|
17059
17059
|
space: input.primarySpaceId,
|
|
@@ -17086,6 +17086,9 @@ var init_authority_sign_in = __esm({
|
|
|
17086
17086
|
|
|
17087
17087
|
// src/replication/config.ts
|
|
17088
17088
|
function assertValidReplicationConfig(replication) {
|
|
17089
|
+
if (replication?.syncScope !== void 0 && replication.syncScope !== "prefixes") {
|
|
17090
|
+
throw new TypeError('replication.syncScope must be "prefixes"');
|
|
17091
|
+
}
|
|
17089
17092
|
if (replication === void 0 || !replication.enabled) return;
|
|
17090
17093
|
if (replication.storage === void 0 || replication.storage === null) {
|
|
17091
17094
|
throw new TypeError("replication.enabled requires replication.storage");
|
|
@@ -17411,6 +17414,7 @@ __export(authority_exports, {
|
|
|
17411
17414
|
assertValidReplicationConfig: () => assertValidReplicationConfig,
|
|
17412
17415
|
augmentSignInEntriesWithReplication: () => augmentSignInEntriesWithReplication,
|
|
17413
17416
|
createReplicationAuthority: () => createReplicationAuthority,
|
|
17417
|
+
eraseReplicaLocalCopy: () => eraseReplicaLocalCopy,
|
|
17414
17418
|
establishReplicaSessionStamp: () => establishReplicaSessionStamp,
|
|
17415
17419
|
hasUnrestrictedGetCoverage: () => hasUnrestrictedGetCoverage,
|
|
17416
17420
|
mintNodeReplicationGrant: () => mintNodeReplicationGrant,
|
|
@@ -17441,6 +17445,38 @@ function reportReplicaDenial(result, reason, onEvent, context) {
|
|
|
17441
17445
|
} catch {
|
|
17442
17446
|
}
|
|
17443
17447
|
}
|
|
17448
|
+
async function eraseReplicaLocalCopy(lifecycle, trigger, denyStatus, handlers) {
|
|
17449
|
+
if (lifecycle?.kind !== "indexeddb" || lifecycle.eraseLocalCopy === void 0) return void 0;
|
|
17450
|
+
let outcome = { status: "failed", code: "STORAGE_ERROR", marker: false };
|
|
17451
|
+
for (let attempt = 0; attempt <= ERASE_RETRY_DELAYS_MS.length; attempt++) {
|
|
17452
|
+
if (attempt > 0) await new Promise((resolve2) => setTimeout(resolve2, ERASE_RETRY_DELAYS_MS[attempt - 1]));
|
|
17453
|
+
try {
|
|
17454
|
+
outcome = await lifecycle.eraseLocalCopy({ signal: AbortSignal.timeout(ERASE_ATTEMPT_MS) });
|
|
17455
|
+
} catch {
|
|
17456
|
+
outcome = { status: "failed", code: "STORAGE_ERROR", marker: false };
|
|
17457
|
+
}
|
|
17458
|
+
if (outcome.status !== "failed") break;
|
|
17459
|
+
}
|
|
17460
|
+
const keysKept = denyStatus === "marker" || denyStatus === "unguarded";
|
|
17461
|
+
const purge = outcome.status === "erased" ? { ok: true } : { ok: false, retryNow: outcome.status === "failed" };
|
|
17462
|
+
if (outcome.status === "erased" || outcome.status === "refused" && !keysKept) return { outcome, purge };
|
|
17463
|
+
const logoutPending = outcome.status === "failed" && outcome.marker;
|
|
17464
|
+
const event = {
|
|
17465
|
+
type: "replica.purge.failed",
|
|
17466
|
+
trigger,
|
|
17467
|
+
reason: logoutPending ? "logout_pending" : "gate_unavailable",
|
|
17468
|
+
code: outcome.code,
|
|
17469
|
+
retryNow: outcome.status === "failed"
|
|
17470
|
+
};
|
|
17471
|
+
for (const handler of handlers) {
|
|
17472
|
+
try {
|
|
17473
|
+
handler(event);
|
|
17474
|
+
} catch (error) {
|
|
17475
|
+
console.error('Error in "replica.purge.failed" handler:', error);
|
|
17476
|
+
}
|
|
17477
|
+
}
|
|
17478
|
+
return logoutPending ? { outcome, purge, logoutPending } : { outcome, purge };
|
|
17479
|
+
}
|
|
17444
17480
|
function verifiedOwnerConsentAnchor(session, wasmBindings, exactVerifiedRecap2) {
|
|
17445
17481
|
if (typeof session.siwe !== "string" || typeof session.signature !== "string" || typeof session.address !== "string" || typeof session.chainId !== "number") return null;
|
|
17446
17482
|
try {
|
|
@@ -17699,7 +17735,7 @@ function createReplicationAuthority(host) {
|
|
|
17699
17735
|
};
|
|
17700
17736
|
return authority;
|
|
17701
17737
|
}
|
|
17702
|
-
var import_siwe3, import_sdk_core12, import_replica, parseUcanGrant, KV_GET2, KV_SYNC2, KV_SERVICE2, AUTHORITY_EXPIRY_MARGIN_MS;
|
|
17738
|
+
var import_siwe3, import_sdk_core12, import_replica, parseUcanGrant, ERASE_RETRY_DELAYS_MS, ERASE_ATTEMPT_MS, KV_GET2, KV_SYNC2, KV_SERVICE2, AUTHORITY_EXPIRY_MARGIN_MS;
|
|
17703
17739
|
var init_authority = __esm({
|
|
17704
17740
|
"src/replication/authority.ts"() {
|
|
17705
17741
|
"use strict";
|
|
@@ -17709,6 +17745,8 @@ var init_authority = __esm({
|
|
|
17709
17745
|
init_config();
|
|
17710
17746
|
init_authority_sign_in();
|
|
17711
17747
|
parseUcanGrant = import_replica.parseUcanGrant;
|
|
17748
|
+
ERASE_RETRY_DELAYS_MS = [150, 450];
|
|
17749
|
+
ERASE_ATTEMPT_MS = 3e3;
|
|
17712
17750
|
KV_GET2 = import_sdk_core12.KV.GET;
|
|
17713
17751
|
KV_SYNC2 = import_sdk_core12.KV.SYNC;
|
|
17714
17752
|
KV_SERVICE2 = "tinycloud.kv";
|
|
@@ -21562,6 +21600,7 @@ function replicaRestoreRefusal(error) {
|
|
|
21562
21600
|
case "purge_pending":
|
|
21563
21601
|
case "logout_pending":
|
|
21564
21602
|
case "gate_unavailable":
|
|
21603
|
+
case "wallet_provider_required":
|
|
21565
21604
|
return error.gate;
|
|
21566
21605
|
}
|
|
21567
21606
|
}
|
|
@@ -21596,6 +21635,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21596
21635
|
this.auth = null;
|
|
21597
21636
|
this.tc = null;
|
|
21598
21637
|
this._chainId = 1;
|
|
21638
|
+
this.replicaPurgeFailedHandlers = /* @__PURE__ */ new Set();
|
|
21599
21639
|
/** Mints the replica session stamp on each fresh sign-in (TC-858 §4.1). Undefined when replication is off. */
|
|
21600
21640
|
this.establishReplicaStamp = async (session) => {
|
|
21601
21641
|
const replication = this.config.replication;
|
|
@@ -21802,6 +21842,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21802
21842
|
return instance ? instance.control.purge(input) : runtime.then((ready) => ready.control.purge(input));
|
|
21803
21843
|
},
|
|
21804
21844
|
clearPending: async () => (await runtime).control.clearPending(),
|
|
21845
|
+
purgeLocalCopy: async () => (await this.eraseReplicaLocalCopy("purge_local_copy"))?.purge ?? { ok: false, retryNow: false },
|
|
21805
21846
|
close: async () => (await runtime).control.close()
|
|
21806
21847
|
};
|
|
21807
21848
|
}
|
|
@@ -21856,18 +21897,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21856
21897
|
get freshEncryptionNetworkCreated() {
|
|
21857
21898
|
return this._freshEncryptionNetworkCreated;
|
|
21858
21899
|
}
|
|
21859
|
-
/**
|
|
21860
|
-
* Subscribe to `storage.full`. It fires on the first write any service had
|
|
21861
|
-
* rejected because the owner's TinyCloud storage is full
|
|
21862
|
-
* (`STORAGE_QUOTA_EXCEEDED` or `STORAGE_LIMIT_REACHED`), so an app can show
|
|
21863
|
-
* one read-only banner. Reads keep working. For the signed-in account's own
|
|
21864
|
-
* storage it fires once per episode: the episode ends only when a write to
|
|
21865
|
-
* that storage succeeds, or on sign-out. A `storage.status()` read does not
|
|
21866
|
-
* end it. A rejection on another owner's delegated space fires once per
|
|
21867
|
-
* owner, until that owner's `storage.status()` reports space again. Returns
|
|
21868
|
-
* the unsubscribe function.
|
|
21869
|
-
*/
|
|
21870
21900
|
on(event, handler) {
|
|
21901
|
+
if (event === "replica.purge.failed") {
|
|
21902
|
+
const listener = handler;
|
|
21903
|
+
this.replicaPurgeFailedHandlers.add(listener);
|
|
21904
|
+
return () => {
|
|
21905
|
+
this.replicaPurgeFailedHandlers.delete(listener);
|
|
21906
|
+
};
|
|
21907
|
+
}
|
|
21871
21908
|
if (event !== "storage.full") {
|
|
21872
21909
|
throw new Error(`Unknown TinyCloud event: ${String(event)}`);
|
|
21873
21910
|
}
|
|
@@ -22087,7 +22124,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22087
22124
|
replication: config.replication?.enabled === true ? {
|
|
22088
22125
|
enabled: true,
|
|
22089
22126
|
prefixes: config.replication.prefixes,
|
|
22090
|
-
allowSecrets: config.replication.allowSecrets === true
|
|
22127
|
+
allowSecrets: config.replication.allowSecrets === true,
|
|
22128
|
+
syncScope: config.replication.syncScope
|
|
22091
22129
|
} : void 0
|
|
22092
22130
|
});
|
|
22093
22131
|
this.tc = new import_sdk_core10.TinyCloud(this.auth, {
|
|
@@ -22347,6 +22385,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22347
22385
|
const leavingAuth = this.auth;
|
|
22348
22386
|
const leavingContext = this._serviceContext;
|
|
22349
22387
|
let denied;
|
|
22388
|
+
let erased;
|
|
22350
22389
|
try {
|
|
22351
22390
|
this.teardownSession();
|
|
22352
22391
|
} finally {
|
|
@@ -22357,6 +22396,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22357
22396
|
try {
|
|
22358
22397
|
await this.accountRegistryTail;
|
|
22359
22398
|
await this.quiesceReplicaRuntime();
|
|
22399
|
+
if (denied) erased = await this.eraseReplicaLocalCopy("sign_out", denied.status);
|
|
22360
22400
|
} finally {
|
|
22361
22401
|
if (leavingAddress) {
|
|
22362
22402
|
await (leavingAuth ? leavingAuth.clearPersistedSession(leavingAddress) : this.config.sessionStorage?.clear(leavingAddress));
|
|
@@ -22364,8 +22404,37 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22364
22404
|
}
|
|
22365
22405
|
}
|
|
22366
22406
|
}
|
|
22367
|
-
if (denied?.status === "unguarded") {
|
|
22368
|
-
throw
|
|
22407
|
+
if (denied?.status === "unguarded" && erased?.outcome.status !== "erased") {
|
|
22408
|
+
throw Object.assign(
|
|
22409
|
+
new Error(`Replica gate was not denied (${denied.code ?? "unknown"}); the replica may still be restorable.`),
|
|
22410
|
+
{
|
|
22411
|
+
code: "REPLICA_PURGE_FAILED",
|
|
22412
|
+
reason: "gate_unavailable",
|
|
22413
|
+
retryNow: erased?.outcome.status === "failed"
|
|
22414
|
+
}
|
|
22415
|
+
);
|
|
22416
|
+
}
|
|
22417
|
+
}
|
|
22418
|
+
/**
|
|
22419
|
+
* Erases the browser local copy after a deny (retry, event and next-load marker live in the lazy
|
|
22420
|
+
* replication authority). Never rejects; `undefined` when replication is off or the storage keeps
|
|
22421
|
+
* no browser database.
|
|
22422
|
+
*/
|
|
22423
|
+
async eraseReplicaLocalCopy(trigger, denyStatus) {
|
|
22424
|
+
const replication = this.config.replication;
|
|
22425
|
+
if (!replication?.enabled) return void 0;
|
|
22426
|
+
try {
|
|
22427
|
+
const { eraseReplicaLocalCopy: eraseReplicaLocalCopy2 } = await getNodeReplicationLoaders().authority();
|
|
22428
|
+
const erased = await eraseReplicaLocalCopy2(
|
|
22429
|
+
replication.storage.lifecycle,
|
|
22430
|
+
trigger,
|
|
22431
|
+
denyStatus,
|
|
22432
|
+
this.replicaPurgeFailedHandlers
|
|
22433
|
+
);
|
|
22434
|
+
if (erased?.logoutPending) this.replicaRestoreGate = "logout_pending";
|
|
22435
|
+
return erased;
|
|
22436
|
+
} catch {
|
|
22437
|
+
return void 0;
|
|
22369
22438
|
}
|
|
22370
22439
|
}
|
|
22371
22440
|
/**
|
|
@@ -22529,6 +22598,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22529
22598
|
const priorPrincipal = this.replicaSessionPrincipal ?? (this.address ? (0, import_sdk_core10.pkhDid)(this.address, this._chainId) : void 0);
|
|
22530
22599
|
if (this.config.replication?.enabled && priorPrincipal && priorPrincipal !== nextPrincipal) {
|
|
22531
22600
|
const denial = await this.denyReplicaGate({ reason: "account_switch", principal: priorPrincipal, next: nextPrincipal });
|
|
22601
|
+
if (denial) {
|
|
22602
|
+
await this.quiesceReplicaRuntime();
|
|
22603
|
+
await this.eraseReplicaLocalCopy("account_switch", denial.status);
|
|
22604
|
+
}
|
|
22532
22605
|
this.replicaRestoreGate = denial?.status === "unguarded" ? "gate_unavailable" : "stamp_stale";
|
|
22533
22606
|
}
|
|
22534
22607
|
if (address !== this._address || chainId !== this._chainId) {
|
|
@@ -24509,7 +24582,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24509
24582
|
replication: this.config.replication?.enabled === true ? {
|
|
24510
24583
|
enabled: true,
|
|
24511
24584
|
prefixes: this.config.replication.prefixes,
|
|
24512
|
-
allowSecrets: this.config.replication.allowSecrets === true
|
|
24585
|
+
allowSecrets: this.config.replication.allowSecrets === true,
|
|
24586
|
+
syncScope: this.config.replication.syncScope
|
|
24513
24587
|
} : void 0
|
|
24514
24588
|
});
|
|
24515
24589
|
this.tc = new import_sdk_core10.TinyCloud(this.auth, {
|
|
@@ -24571,7 +24645,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24571
24645
|
replication: this.config.replication?.enabled === true ? {
|
|
24572
24646
|
enabled: true,
|
|
24573
24647
|
prefixes: this.config.replication.prefixes,
|
|
24574
|
-
allowSecrets: this.config.replication.allowSecrets === true
|
|
24648
|
+
allowSecrets: this.config.replication.allowSecrets === true,
|
|
24649
|
+
syncScope: this.config.replication.syncScope
|
|
24575
24650
|
} : void 0
|
|
24576
24651
|
});
|
|
24577
24652
|
this.tc = new import_sdk_core10.TinyCloud(this.auth, {
|