@tinycloud/node-sdk 3.2.6-beta.0 → 3.2.6-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/{WasmKeyProvider-LXRTjZTA.d.cts → WasmKeyProvider-CYU_dqOx.d.cts} +69 -3
- package/dist/{WasmKeyProvider-LXRTjZTA.d.ts → WasmKeyProvider-CYU_dqOx.d.ts} +69 -3
- package/dist/core.cjs +295 -59
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +295 -59
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +295 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +295 -59
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -18494,6 +18494,13 @@ function cloneAbilitiesMap(actions) {
|
|
|
18494
18494
|
var NodeUserAuthorization = class {
|
|
18495
18495
|
constructor(config) {
|
|
18496
18496
|
this.activeSessionKeyId = "default";
|
|
18497
|
+
/** Incremented by resetSession; a sign-in started earlier publishes nothing. */
|
|
18498
|
+
this.sessionGeneration = 0;
|
|
18499
|
+
/**
|
|
18500
|
+
* Sign-in saves run one at a time, in order, each together with its own
|
|
18501
|
+
* cancellation cleanup, so no later write can land between the two.
|
|
18502
|
+
*/
|
|
18503
|
+
this.persistenceQueue = Promise.resolve();
|
|
18497
18504
|
this.extensions = [];
|
|
18498
18505
|
this._nodeFeatures = [];
|
|
18499
18506
|
this._nodeFeaturesKnown = false;
|
|
@@ -18624,6 +18631,27 @@ var NodeUserAuthorization = class {
|
|
|
18624
18631
|
this.tinycloudHosts = [...hosts];
|
|
18625
18632
|
}
|
|
18626
18633
|
}
|
|
18634
|
+
/**
|
|
18635
|
+
* @internal End the session: adopt a fresh session manager whose active key
|
|
18636
|
+
* is `sessionKeyId`, and return to the constructed state.
|
|
18637
|
+
*/
|
|
18638
|
+
resetSession(sessionManager, sessionKeyId, hosts) {
|
|
18639
|
+
this.sessionGeneration++;
|
|
18640
|
+
this.installRestoredSession(sessionManager, void 0, hosts);
|
|
18641
|
+
this.activeSessionKeyId = sessionKeyId;
|
|
18642
|
+
}
|
|
18643
|
+
/** Throws when the session was reset (signed out) after `generation` was read. */
|
|
18644
|
+
assertSignInCurrent(generation) {
|
|
18645
|
+
if (generation !== this.sessionGeneration) {
|
|
18646
|
+
throw new Error("Sign-in was cancelled by sign-out.");
|
|
18647
|
+
}
|
|
18648
|
+
}
|
|
18649
|
+
/** Runs `task` after every earlier queued persistence task has settled. */
|
|
18650
|
+
enqueuePersistence(task) {
|
|
18651
|
+
const run = this.persistenceQueue.then(task);
|
|
18652
|
+
this.persistenceQueue = run.catch(() => void 0);
|
|
18653
|
+
return run;
|
|
18654
|
+
}
|
|
18627
18655
|
/** @internal Atomically adopt the state staged by TinyCloudNode.restoreSession. */
|
|
18628
18656
|
installRestoredSession(sessionManager, session, hosts, nodeFeatures) {
|
|
18629
18657
|
this.sessionManager = sessionManager;
|
|
@@ -19312,11 +19340,14 @@ var NodeUserAuthorization = class {
|
|
|
19312
19340
|
* @param options - Optional per-call SIWE overrides for this sign-in only
|
|
19313
19341
|
*/
|
|
19314
19342
|
async signIn(options) {
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
const
|
|
19318
|
-
|
|
19343
|
+
const generation = this.sessionGeneration;
|
|
19344
|
+
const address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
|
|
19345
|
+
const chainId = await this.signer.getChainId();
|
|
19346
|
+
this.assertSignInCurrent(generation);
|
|
19347
|
+
this._address = address;
|
|
19348
|
+
this._chainId = chainId;
|
|
19319
19349
|
await this.resolveTinyCloudHostsForSignIn(address, chainId);
|
|
19350
|
+
this.assertSignInCurrent(generation);
|
|
19320
19351
|
const keyId = `session-${Date.now()}`;
|
|
19321
19352
|
this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
|
|
19322
19353
|
this.activeSessionKeyId = keyId;
|
|
@@ -19349,6 +19380,7 @@ var NodeUserAuthorization = class {
|
|
|
19349
19380
|
type: "siwe",
|
|
19350
19381
|
purpose: "sign-in"
|
|
19351
19382
|
});
|
|
19383
|
+
this.assertSignInCurrent(generation);
|
|
19352
19384
|
const session = this.wasm.completeSessionSetup({
|
|
19353
19385
|
...prepared,
|
|
19354
19386
|
signature: signature2
|
|
@@ -19393,18 +19425,27 @@ var NodeUserAuthorization = class {
|
|
|
19393
19425
|
version: "1.0",
|
|
19394
19426
|
tinycloudHosts: this.tinycloudHosts
|
|
19395
19427
|
};
|
|
19396
|
-
await this.
|
|
19428
|
+
await this.enqueuePersistence(async () => {
|
|
19429
|
+
await this.sessionStorage.save(address, persistedData);
|
|
19430
|
+
if (generation !== this.sessionGeneration) {
|
|
19431
|
+
await this.sessionStorage.clear(address);
|
|
19432
|
+
}
|
|
19433
|
+
});
|
|
19434
|
+
this.assertSignInCurrent(generation);
|
|
19397
19435
|
this._session = clientSession;
|
|
19398
19436
|
this._tinyCloudSession = tinyCloudSession;
|
|
19399
19437
|
this._address = address;
|
|
19400
19438
|
this._chainId = chainId;
|
|
19401
19439
|
await this.refreshNodeInfo();
|
|
19440
|
+
this.assertSignInCurrent(generation);
|
|
19402
19441
|
for (const ext of this.extensions) {
|
|
19403
19442
|
if (ext.afterSignIn) {
|
|
19404
19443
|
await ext.afterSignIn(clientSession);
|
|
19444
|
+
this.assertSignInCurrent(generation);
|
|
19405
19445
|
}
|
|
19406
19446
|
}
|
|
19407
19447
|
await this.ensureSpaceExists();
|
|
19448
|
+
this.assertSignInCurrent(generation);
|
|
19408
19449
|
return clientSession;
|
|
19409
19450
|
}
|
|
19410
19451
|
/**
|
|
@@ -20041,17 +20082,24 @@ var import_sdk_core5 = require("@tinycloud/sdk-core");
|
|
|
20041
20082
|
// src/DelegatedAccess.ts
|
|
20042
20083
|
var import_sdk_core6 = require("@tinycloud/sdk-core");
|
|
20043
20084
|
var DelegatedAccess = class {
|
|
20044
|
-
|
|
20085
|
+
/**
|
|
20086
|
+
* @param lifetime - Optional owner of this access: its `fetch` is used for
|
|
20087
|
+
* requests and the service context is registered with `track`, so the
|
|
20088
|
+
* owner can cancel and retire the access (TinyCloudNode does this when its
|
|
20089
|
+
* session is replaced or signed out).
|
|
20090
|
+
*/
|
|
20091
|
+
constructor(session, delegation, host, invoke2, invokeAny2, telemetry, lifetime) {
|
|
20045
20092
|
this.session = session;
|
|
20046
20093
|
this._delegation = delegation;
|
|
20047
20094
|
this.host = host;
|
|
20048
|
-
|
|
20095
|
+
const context = new import_sdk_core6.ServiceContext({
|
|
20049
20096
|
invoke: invoke2,
|
|
20050
20097
|
invokeAny: invokeAny2,
|
|
20051
|
-
fetch: globalThis.fetch.bind(globalThis),
|
|
20098
|
+
fetch: lifetime?.fetch ?? globalThis.fetch.bind(globalThis),
|
|
20052
20099
|
hosts: [host],
|
|
20053
20100
|
telemetry
|
|
20054
20101
|
});
|
|
20102
|
+
this._serviceContext = lifetime ? lifetime.track(context) : context;
|
|
20055
20103
|
const prefix = this._delegation.path.replace(/\/$/, "");
|
|
20056
20104
|
this._kv = new import_sdk_core6.KVService({ prefix });
|
|
20057
20105
|
this._kv.initialize(this._serviceContext);
|
|
@@ -20625,6 +20673,19 @@ function exactVerifiedRecap(verified) {
|
|
|
20625
20673
|
caveats: cloneRecapCaveats(entry.caveats)
|
|
20626
20674
|
}));
|
|
20627
20675
|
}
|
|
20676
|
+
function createDefaultSessionKey(wasm) {
|
|
20677
|
+
const manager = wasm.createSessionManager();
|
|
20678
|
+
let keyId = "default";
|
|
20679
|
+
let jwkStr = manager.jwk(keyId);
|
|
20680
|
+
if (!jwkStr) {
|
|
20681
|
+
keyId = manager.createSessionKey(keyId);
|
|
20682
|
+
jwkStr = manager.jwk(keyId);
|
|
20683
|
+
}
|
|
20684
|
+
if (!jwkStr) {
|
|
20685
|
+
throw new Error("Failed to get session key JWK");
|
|
20686
|
+
}
|
|
20687
|
+
return { manager, keyId, jwk: JSON.parse(jwkStr) };
|
|
20688
|
+
}
|
|
20628
20689
|
var ServiceGraphLifetime = class {
|
|
20629
20690
|
constructor(invokeFn, invokeAnyFn, fetchFn, observeContext) {
|
|
20630
20691
|
this.invokeFn = invokeFn;
|
|
@@ -20674,9 +20735,13 @@ var ServiceGraphLifetime = class {
|
|
|
20674
20735
|
this.contexts.clear();
|
|
20675
20736
|
}
|
|
20676
20737
|
}
|
|
20738
|
+
/** Aborted when the graph retires: cancels requests made for its session. */
|
|
20739
|
+
get signal() {
|
|
20740
|
+
return this.abortController.signal;
|
|
20741
|
+
}
|
|
20677
20742
|
assertActive() {
|
|
20678
20743
|
if (this.retired) {
|
|
20679
|
-
throw new Error("Service graph has been retired
|
|
20744
|
+
throw new Error("Service graph has been retired: its session was replaced or signed out.");
|
|
20680
20745
|
}
|
|
20681
20746
|
}
|
|
20682
20747
|
combineSignals(signal) {
|
|
@@ -20978,6 +21043,16 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20978
21043
|
* so it must outlast a slow but healthy sync (9–18 s on prod 1.20.2, TC-998).
|
|
20979
21044
|
*/
|
|
20980
21045
|
this.accountRegistryDeadlineMs = 3e4;
|
|
21046
|
+
/**
|
|
21047
|
+
* Incremented by every sign-out. A sign-in or restore records it when it
|
|
21048
|
+
* starts and does not establish its session once it has changed.
|
|
21049
|
+
*/
|
|
21050
|
+
this.sessionEpoch = 0;
|
|
21051
|
+
/**
|
|
21052
|
+
* Numbers sign-in and restore attempts. A cancelled attempt cleans up only
|
|
21053
|
+
* while it is still the latest, so it never ends a newer session.
|
|
21054
|
+
*/
|
|
21055
|
+
this.latestSessionAttempt = 0;
|
|
20981
21056
|
/**
|
|
20982
21057
|
* True when the last signIn() detected an interactive signer and skipped
|
|
20983
21058
|
* client-side bootstrap. Apps can read this to know whether bootstrap was
|
|
@@ -21111,54 +21186,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21111
21186
|
"wasmBindings must be provided in config. Import from '@tinycloud/node-sdk' (not '/core') for automatic Node.js defaults."
|
|
21112
21187
|
);
|
|
21113
21188
|
}
|
|
21114
|
-
|
|
21115
|
-
|
|
21116
|
-
|
|
21117
|
-
|
|
21118
|
-
this.sessionKeyId = defaultKeyId;
|
|
21119
|
-
} else {
|
|
21120
|
-
this.sessionKeyId = this.sessionManager.createSessionKey(defaultKeyId);
|
|
21121
|
-
jwkStr = this.sessionManager.jwk(this.sessionKeyId);
|
|
21122
|
-
}
|
|
21123
|
-
if (!jwkStr) {
|
|
21124
|
-
throw new Error("Failed to get session key JWK");
|
|
21125
|
-
}
|
|
21126
|
-
this.sessionKeyJwk = JSON.parse(jwkStr);
|
|
21189
|
+
const sessionKey = createDefaultSessionKey(this.wasmBindings);
|
|
21190
|
+
this.sessionManager = sessionKey.manager;
|
|
21191
|
+
this.sessionKeyId = sessionKey.keyId;
|
|
21192
|
+
this.sessionKeyJwk = sessionKey.jwk;
|
|
21127
21193
|
this._serviceGraph = this.createServiceGraphLifetime();
|
|
21128
21194
|
this._capabilityRegistry = new import_sdk_core9.CapabilityKeyRegistry();
|
|
21129
21195
|
this._keyProvider = new WasmKeyProvider({
|
|
21130
21196
|
sessionManager: this.sessionManager
|
|
21131
21197
|
});
|
|
21132
21198
|
this.notificationHandler = config.notificationHandler ?? new import_sdk_core9.SilentNotificationHandler();
|
|
21133
|
-
|
|
21134
|
-
this._sharingService = new import_sdk_core9.SharingService({
|
|
21135
|
-
hosts: [this.config.host],
|
|
21136
|
-
// session: undefined - not needed for receive()
|
|
21137
|
-
invoke: receiveOnlyGraph.invoke,
|
|
21138
|
-
fetch: receiveOnlyGraph.fetch,
|
|
21139
|
-
assertActive: () => receiveOnlyGraph.assertActive(),
|
|
21140
|
-
keyProvider: this._keyProvider,
|
|
21141
|
-
registry: this._capabilityRegistry,
|
|
21142
|
-
createDelegationWasm: (params) => this.createDelegationWrapper(params),
|
|
21143
|
-
computeCid: (data, codec) => {
|
|
21144
|
-
if (!this.wasmBindings.computeCid) throw new Error("computeCid is unavailable");
|
|
21145
|
-
return this.wasmBindings.computeCid(data, codec);
|
|
21146
|
-
},
|
|
21147
|
-
// delegationManager: undefined - not needed for receive()
|
|
21148
|
-
createKVService: (config2) => {
|
|
21149
|
-
const prefix = config2.pathPrefix?.replace(/\/$/, "");
|
|
21150
|
-
const kvService = new import_sdk_core9.KVService({ prefix });
|
|
21151
|
-
const kvContext = receiveOnlyGraph.track(new import_sdk_core9.ServiceContext({
|
|
21152
|
-
invoke: config2.invoke,
|
|
21153
|
-
fetch: config2.fetch ?? globalThis.fetch.bind(globalThis),
|
|
21154
|
-
hosts: config2.hosts,
|
|
21155
|
-
telemetry: this.config.telemetry
|
|
21156
|
-
}));
|
|
21157
|
-
kvContext.setSession(config2.session);
|
|
21158
|
-
kvService.initialize(kvContext);
|
|
21159
|
-
return kvService;
|
|
21160
|
-
}
|
|
21161
|
-
});
|
|
21199
|
+
this._sharingService = this.createReceiveOnlySharing();
|
|
21162
21200
|
if (config.signer) {
|
|
21163
21201
|
this.signer = config.signer;
|
|
21164
21202
|
this.setupAuth(config);
|
|
@@ -21300,6 +21338,42 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21300
21338
|
get siweDomain() {
|
|
21301
21339
|
return this.config.domain ?? "app.tinycloud.xyz";
|
|
21302
21340
|
}
|
|
21341
|
+
/**
|
|
21342
|
+
* SharingService for receive-only access (no session required), bound to the
|
|
21343
|
+
* current service graph. This lets session-only users receive sharing links
|
|
21344
|
+
* without signIn(); full capabilities (generate) are added after signIn().
|
|
21345
|
+
*/
|
|
21346
|
+
createReceiveOnlySharing() {
|
|
21347
|
+
const receiveOnlyGraph = this._serviceGraph;
|
|
21348
|
+
return new import_sdk_core9.SharingService({
|
|
21349
|
+
hosts: [this.config.host],
|
|
21350
|
+
// session: undefined - not needed for receive()
|
|
21351
|
+
invoke: receiveOnlyGraph.invoke,
|
|
21352
|
+
fetch: receiveOnlyGraph.fetch,
|
|
21353
|
+
assertActive: () => receiveOnlyGraph.assertActive(),
|
|
21354
|
+
keyProvider: this._keyProvider,
|
|
21355
|
+
registry: this._capabilityRegistry,
|
|
21356
|
+
createDelegationWasm: (params) => this.createDelegationWrapper(params),
|
|
21357
|
+
computeCid: (data, codec) => {
|
|
21358
|
+
if (!this.wasmBindings.computeCid) throw new Error("computeCid is unavailable");
|
|
21359
|
+
return this.wasmBindings.computeCid(data, codec);
|
|
21360
|
+
},
|
|
21361
|
+
// delegationManager: undefined - not needed for receive()
|
|
21362
|
+
createKVService: (config) => {
|
|
21363
|
+
const prefix = config.pathPrefix?.replace(/\/$/, "");
|
|
21364
|
+
const kvService = new import_sdk_core9.KVService({ prefix });
|
|
21365
|
+
const kvContext = receiveOnlyGraph.track(new import_sdk_core9.ServiceContext({
|
|
21366
|
+
invoke: config.invoke,
|
|
21367
|
+
fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
|
|
21368
|
+
hosts: config.hosts,
|
|
21369
|
+
telemetry: this.config.telemetry
|
|
21370
|
+
}));
|
|
21371
|
+
kvContext.setSession(config.session);
|
|
21372
|
+
kvService.initialize(kvContext);
|
|
21373
|
+
return kvService;
|
|
21374
|
+
}
|
|
21375
|
+
});
|
|
21376
|
+
}
|
|
21303
21377
|
/**
|
|
21304
21378
|
* Set up authorization handler and TinyCloud instance.
|
|
21305
21379
|
* @internal
|
|
@@ -21559,6 +21633,102 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21559
21633
|
get restorableSession() {
|
|
21560
21634
|
return this.currentTinyCloudSession();
|
|
21561
21635
|
}
|
|
21636
|
+
/**
|
|
21637
|
+
* Sign out and end the session on this instance.
|
|
21638
|
+
*
|
|
21639
|
+
* Every service built for the session (and every `useDelegation()` result)
|
|
21640
|
+
* is retired and the session key is replaced before anything is awaited, so
|
|
21641
|
+
* nothing captured from the session can sign once sign-out has started.
|
|
21642
|
+
* Pending work is aborted and the persisted session is cleared from the
|
|
21643
|
+
* configured session storage. Afterwards session accessors return
|
|
21644
|
+
* `undefined` and service calls fail with "Not signed in" until
|
|
21645
|
+
* {@link signIn} or {@link restoreSession}, which wait for a sign-out in
|
|
21646
|
+
* progress.
|
|
21647
|
+
*/
|
|
21648
|
+
signOut() {
|
|
21649
|
+
this.signOutInFlight ?? (this.signOutInFlight = this.endSession().finally(() => {
|
|
21650
|
+
this.signOutInFlight = void 0;
|
|
21651
|
+
}));
|
|
21652
|
+
return this.signOutInFlight;
|
|
21653
|
+
}
|
|
21654
|
+
async endSession() {
|
|
21655
|
+
const leavingAddress = this.address ?? this._restoredTcSession?.address;
|
|
21656
|
+
this.teardownSession();
|
|
21657
|
+
try {
|
|
21658
|
+
await this.accountRegistryTail;
|
|
21659
|
+
if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
|
|
21660
|
+
} finally {
|
|
21661
|
+
if (leavingAddress) await this.clearPersistedSessionFor(leavingAddress);
|
|
21662
|
+
}
|
|
21663
|
+
}
|
|
21664
|
+
/**
|
|
21665
|
+
* Synchronously drop every piece of in-memory session authority and
|
|
21666
|
+
* invalidate sign-ins and restores still in flight (see `sessionEpoch`).
|
|
21667
|
+
*/
|
|
21668
|
+
teardownSession() {
|
|
21669
|
+
this.sessionEpoch++;
|
|
21670
|
+
this.pendingAccountRegistrySync?.controller.abort();
|
|
21671
|
+
const oldGraph = this._serviceGraph;
|
|
21672
|
+
const oldCore = this.tc;
|
|
21673
|
+
const sessionKey = createDefaultSessionKey(this.wasmBindings);
|
|
21674
|
+
this.sessionManager = sessionKey.manager;
|
|
21675
|
+
this.sessionKeyId = sessionKey.keyId;
|
|
21676
|
+
this.sessionKeyJwk = sessionKey.jwk;
|
|
21677
|
+
this.auth?.resetSession(
|
|
21678
|
+
sessionKey.manager,
|
|
21679
|
+
sessionKey.keyId,
|
|
21680
|
+
this.explicitHost ? [this.explicitHost] : void 0
|
|
21681
|
+
);
|
|
21682
|
+
this.config.host = this.explicitHost ?? DEFAULT_HOST;
|
|
21683
|
+
this._address = void 0;
|
|
21684
|
+
this._chainId = 1;
|
|
21685
|
+
this._restoredTcSession = void 0;
|
|
21686
|
+
this._restoredNodeFeatures = void 0;
|
|
21687
|
+
this._activeServiceSession = void 0;
|
|
21688
|
+
this._serviceContext = void 0;
|
|
21689
|
+
this._kv = void 0;
|
|
21690
|
+
this._sql = void 0;
|
|
21691
|
+
this._duckdb = void 0;
|
|
21692
|
+
this._hooks = void 0;
|
|
21693
|
+
this._vault = void 0;
|
|
21694
|
+
this._encryption = void 0;
|
|
21695
|
+
this._baseVaults.clear();
|
|
21696
|
+
this._baseSecrets.clear();
|
|
21697
|
+
this._secrets.clear();
|
|
21698
|
+
this._account = void 0;
|
|
21699
|
+
this._publicKV = void 0;
|
|
21700
|
+
this._delegationManager = void 0;
|
|
21701
|
+
this._spaceService = void 0;
|
|
21702
|
+
this.runtimePermissionGrants = [];
|
|
21703
|
+
this._recapOperationsCache = void 0;
|
|
21704
|
+
this.confirmedHostedSpaceIds.clear();
|
|
21705
|
+
this.hostedOwnedSpaceIds.clear();
|
|
21706
|
+
this.cancelOwnedSpaceHosts();
|
|
21707
|
+
this.storageFull.clear();
|
|
21708
|
+
this._bootstrapSkipped = false;
|
|
21709
|
+
this._bootstrapStatus = { skipped: false };
|
|
21710
|
+
this.replicationDelegateSession = void 0;
|
|
21711
|
+
this.replicationScopeError = void 0;
|
|
21712
|
+
this._serviceGraph = this.createServiceGraphLifetime();
|
|
21713
|
+
oldGraph.retire();
|
|
21714
|
+
this.tc = this.auth ? new import_sdk_core9.TinyCloud(this.auth, {
|
|
21715
|
+
invokeAny: this.invokeAnyWithRuntimePermissions,
|
|
21716
|
+
telemetry: this.config.telemetry
|
|
21717
|
+
}) : null;
|
|
21718
|
+
oldCore?.retireServices();
|
|
21719
|
+
this._capabilityRegistry = new import_sdk_core9.CapabilityKeyRegistry();
|
|
21720
|
+
this._keyProvider = new WasmKeyProvider({ sessionManager: this.sessionManager });
|
|
21721
|
+
this._sharingService = this.createReceiveOnlySharing();
|
|
21722
|
+
}
|
|
21723
|
+
async clearPersistedSessionFor(address) {
|
|
21724
|
+
await (this.auth ? this.auth.clearPersistedSession(address) : this.config.sessionStorage?.clear(address));
|
|
21725
|
+
}
|
|
21726
|
+
/** Throws when a sign-out started after `epoch` was read. */
|
|
21727
|
+
assertSessionEpoch(epoch, operation) {
|
|
21728
|
+
if (epoch !== this.sessionEpoch) {
|
|
21729
|
+
throw new Error(`${operation} was cancelled by sign-out.`);
|
|
21730
|
+
}
|
|
21731
|
+
}
|
|
21562
21732
|
/**
|
|
21563
21733
|
* Sign in and create a new session.
|
|
21564
21734
|
* This creates the user's space if it doesn't exist.
|
|
@@ -21572,11 +21742,28 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21572
21742
|
"Cannot signIn() in session-only mode. Provide a privateKey in config to create your own space."
|
|
21573
21743
|
);
|
|
21574
21744
|
}
|
|
21745
|
+
const epoch = this.sessionEpoch;
|
|
21746
|
+
const attempt = ++this.latestSessionAttempt;
|
|
21747
|
+
await this.signOutInFlight;
|
|
21748
|
+
try {
|
|
21749
|
+
await this.establishSignIn(epoch, options);
|
|
21750
|
+
} catch (error) {
|
|
21751
|
+
if (epoch !== this.sessionEpoch && attempt === this.latestSessionAttempt) {
|
|
21752
|
+
await this.endSession();
|
|
21753
|
+
}
|
|
21754
|
+
throw error;
|
|
21755
|
+
}
|
|
21756
|
+
}
|
|
21757
|
+
async establishSignIn(epoch, options) {
|
|
21758
|
+
if (!this.signer || !this.tc) {
|
|
21759
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
21760
|
+
}
|
|
21575
21761
|
this.pendingAccountRegistrySync?.controller.abort();
|
|
21576
21762
|
await this.accountRegistryTail;
|
|
21577
21763
|
await this.wasmBindings.ensureInitialized?.();
|
|
21578
21764
|
const address = (0, import_sdk_core9.canonicalizeAddress)(await this.signer.getAddress());
|
|
21579
21765
|
const chainId = await this.signer.getChainId();
|
|
21766
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
21580
21767
|
if (address !== this._address || chainId !== this._chainId) this.storageFull.clear();
|
|
21581
21768
|
this._address = address;
|
|
21582
21769
|
this._chainId = chainId;
|
|
@@ -21595,6 +21782,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21595
21782
|
this.confirmedHostedSpaceIds.clear();
|
|
21596
21783
|
this.hostedOwnedSpaceIds.clear();
|
|
21597
21784
|
await this.tc.signIn(options);
|
|
21785
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
21598
21786
|
this.cancelOwnedSpaceHosts();
|
|
21599
21787
|
this.syncResolvedHostFromAuth();
|
|
21600
21788
|
for (const spaceId of this.auth.lastActivationActivatedSpaceIds ?? []) {
|
|
@@ -21603,6 +21791,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21603
21791
|
this.replicationDelegateSession = void 0;
|
|
21604
21792
|
this.replicationScopeError = void 0;
|
|
21605
21793
|
if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
|
|
21794
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
21606
21795
|
const oldGraph = this._serviceGraph;
|
|
21607
21796
|
this._serviceGraph = this.createServiceGraphLifetime();
|
|
21608
21797
|
oldGraph.retire();
|
|
@@ -21613,15 +21802,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21613
21802
|
this.sessionKeyJwk = signedInSession.jwk;
|
|
21614
21803
|
}
|
|
21615
21804
|
await this.initializeServices();
|
|
21805
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
21616
21806
|
const primarySession = this.currentTinyCloudSession();
|
|
21617
21807
|
if (primarySession) {
|
|
21618
21808
|
this.registerPrimarySessionGrant(primarySession);
|
|
21619
21809
|
}
|
|
21620
21810
|
const bootstrapped = await this.bootstrapAccountIfNeeded();
|
|
21811
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
21621
21812
|
await this.ensureRequestedEncryptionNetworks();
|
|
21813
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
21622
21814
|
if (!bootstrapped && this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
|
|
21623
21815
|
await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(import_sdk_core9.SECRETS_SPACE));
|
|
21624
21816
|
}
|
|
21817
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
21625
21818
|
if (!bootstrapped) {
|
|
21626
21819
|
this.scheduleAccountRegistrySync();
|
|
21627
21820
|
}
|
|
@@ -21803,6 +21996,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21803
21996
|
throw new Error("Account bootstrap requires a TinyCloud host");
|
|
21804
21997
|
}
|
|
21805
21998
|
const auth = this.auth;
|
|
21999
|
+
const graph = this._serviceGraph;
|
|
21806
22000
|
const sessions = /* @__PURE__ */ new Map();
|
|
21807
22001
|
const rawAbilitiesBySpace = /* @__PURE__ */ new Map();
|
|
21808
22002
|
const warnings = [];
|
|
@@ -21811,6 +22005,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21811
22005
|
const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default;
|
|
21812
22006
|
for (const step of steps) {
|
|
21813
22007
|
if (step.kind !== "session") continue;
|
|
22008
|
+
graph.assertActive();
|
|
21814
22009
|
if (step.space === "default" && canReusePrimaryBootstrapSession && primarySession) {
|
|
21815
22010
|
sessions.set(step.space, primarySession);
|
|
21816
22011
|
continue;
|
|
@@ -21838,6 +22033,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21838
22033
|
}
|
|
21839
22034
|
for (const step of steps) {
|
|
21840
22035
|
if (step.kind !== "host") continue;
|
|
22036
|
+
graph.assertActive();
|
|
21841
22037
|
const hosted = await auth.hostOwnedSpaceResult(step.spaceId, "bootstrap-host");
|
|
21842
22038
|
if (!hosted.success) {
|
|
21843
22039
|
throw Object.assign(
|
|
@@ -21849,11 +22045,16 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21849
22045
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
21850
22046
|
for (const step of steps) {
|
|
21851
22047
|
if (step.kind !== "activate") continue;
|
|
22048
|
+
graph.assertActive();
|
|
21852
22049
|
const session = sessions.get(step.space);
|
|
21853
22050
|
if (!session) {
|
|
21854
22051
|
throw new Error(`Missing bootstrap session for ${step.space}`);
|
|
21855
22052
|
}
|
|
21856
|
-
const activated = await (0, import_sdk_core9.activateSessionWithHost)(host, session.delegationHeader)
|
|
22053
|
+
const activated = await (0, import_sdk_core9.activateSessionWithHost)(host, session.delegationHeader, graph.signal).catch((error) => {
|
|
22054
|
+
graph.assertActive();
|
|
22055
|
+
throw error;
|
|
22056
|
+
});
|
|
22057
|
+
graph.assertActive();
|
|
21857
22058
|
if (!activated.success || activated.skipped?.includes(step.spaceId)) {
|
|
21858
22059
|
throw Object.assign(
|
|
21859
22060
|
new Error(
|
|
@@ -21869,6 +22070,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21869
22070
|
);
|
|
21870
22071
|
}
|
|
21871
22072
|
for (const step of steps) {
|
|
22073
|
+
graph.assertActive();
|
|
21872
22074
|
if (step.kind === "account-index-schema") {
|
|
21873
22075
|
const ensured = await this.account.index.ensure();
|
|
21874
22076
|
if (!ensured.ok) {
|
|
@@ -22644,6 +22846,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22644
22846
|
* @param sessionData - The stored delegation data from the browser flow
|
|
22645
22847
|
*/
|
|
22646
22848
|
async restoreSession(sessionData) {
|
|
22849
|
+
const epoch = this.sessionEpoch;
|
|
22850
|
+
const attempt = ++this.latestSessionAttempt;
|
|
22851
|
+
await this.signOutInFlight;
|
|
22647
22852
|
await this.wasmBindings.ensureInitialized?.();
|
|
22648
22853
|
let restoredJwk;
|
|
22649
22854
|
try {
|
|
@@ -22833,6 +23038,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22833
23038
|
});
|
|
22834
23039
|
this.pendingAccountRegistrySync?.controller.abort();
|
|
22835
23040
|
await this.accountRegistryTail;
|
|
23041
|
+
this.assertSessionEpoch(epoch, "Session restore");
|
|
22836
23042
|
const oldGraph = this._serviceGraph;
|
|
22837
23043
|
const oldCore = this.tc;
|
|
22838
23044
|
this.sessionManager = stagedManager;
|
|
@@ -22878,6 +23084,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22878
23084
|
this.replicationDelegateSession = compactReplicationSession;
|
|
22879
23085
|
this.replicationScopeError = replicationScopeError;
|
|
22880
23086
|
if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
|
|
23087
|
+
if (epoch !== this.sessionEpoch) {
|
|
23088
|
+
oldGraph.retire();
|
|
23089
|
+
oldCore?.retireServices?.();
|
|
23090
|
+
if (attempt === this.latestSessionAttempt) await this.endSession();
|
|
23091
|
+
this.assertSessionEpoch(epoch, "Session restore");
|
|
23092
|
+
}
|
|
22881
23093
|
oldGraph.retire();
|
|
22882
23094
|
if (replicationScopeError) {
|
|
22883
23095
|
stagedGraph.serviceContext.emit("replication.state", {
|
|
@@ -22888,6 +23100,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22888
23100
|
}
|
|
22889
23101
|
await this.bindReplicationRuntime(stagedGraph.serviceContext, serviceSession, stagedGraph.kv, replicationPrincipal);
|
|
22890
23102
|
oldCore?.retireServices?.();
|
|
23103
|
+
if (epoch !== this.sessionEpoch) {
|
|
23104
|
+
if (attempt === this.latestSessionAttempt) await this.endSession();
|
|
23105
|
+
this.assertSessionEpoch(epoch, "Session restore");
|
|
23106
|
+
}
|
|
22891
23107
|
}
|
|
22892
23108
|
stagePrimarySessionState(session, verificationMethod, host, sessionExpiry, recap) {
|
|
22893
23109
|
if (!session?.siwe) return { cache: void 0, grants: [] };
|
|
@@ -24746,6 +24962,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24746
24962
|
* matching service calls and downstream `delegateTo()` calls can use it.
|
|
24747
24963
|
*/
|
|
24748
24964
|
async useRuntimeDelegation(delegation) {
|
|
24965
|
+
const graph = this._serviceGraph;
|
|
24749
24966
|
const session = this.currentTinyCloudSession();
|
|
24750
24967
|
if (!session) {
|
|
24751
24968
|
throw new import_sdk_core9.SessionExpiredError(/* @__PURE__ */ new Date(0));
|
|
@@ -24764,9 +24981,11 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24764
24981
|
try {
|
|
24765
24982
|
activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
|
|
24766
24983
|
targetHost,
|
|
24767
|
-
delegation.delegationHeader
|
|
24984
|
+
delegation.delegationHeader,
|
|
24985
|
+
graph.signal
|
|
24768
24986
|
);
|
|
24769
24987
|
} catch (cause) {
|
|
24988
|
+
graph.assertActive();
|
|
24770
24989
|
throw Object.assign(
|
|
24771
24990
|
new Error("The TinyCloud host could not be reached to activate the delegation."),
|
|
24772
24991
|
{ code: "ACTIVATION_TRANSPORT_FAILED", cause }
|
|
@@ -24786,6 +25005,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24786
25005
|
{ cause: activateResult }
|
|
24787
25006
|
);
|
|
24788
25007
|
}
|
|
25008
|
+
graph.assertActive();
|
|
24789
25009
|
this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
|
|
24790
25010
|
(grant) => grant.delegation.cid !== delegation.cid
|
|
24791
25011
|
);
|
|
@@ -24802,6 +25022,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24802
25022
|
if (!Array.isArray(permissions) || permissions.length === 0) {
|
|
24803
25023
|
throw new Error("grantRuntimePermissions requires a non-empty permissions array");
|
|
24804
25024
|
}
|
|
25025
|
+
const graph = this._serviceGraph;
|
|
24805
25026
|
const session = this.currentTinyCloudSession();
|
|
24806
25027
|
if (!session) {
|
|
24807
25028
|
throw new import_sdk_core9.SessionExpiredError(/* @__PURE__ */ new Date(0));
|
|
@@ -24882,14 +25103,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24882
25103
|
}
|
|
24883
25104
|
})();
|
|
24884
25105
|
const signature2 = await this.signer.signMessage(prepared.siwe);
|
|
25106
|
+
graph.assertActive();
|
|
24885
25107
|
const delegatedSession = this.wasmBindings.completeSessionSetup({
|
|
24886
25108
|
...prepared,
|
|
24887
25109
|
signature: signature2
|
|
24888
25110
|
});
|
|
24889
25111
|
const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
|
|
24890
25112
|
this.config.host,
|
|
24891
|
-
delegatedSession.delegationHeader
|
|
24892
|
-
|
|
25113
|
+
delegatedSession.delegationHeader,
|
|
25114
|
+
graph.signal
|
|
25115
|
+
).catch((error) => {
|
|
25116
|
+
graph.assertActive();
|
|
25117
|
+
throw error;
|
|
25118
|
+
});
|
|
24893
25119
|
if (!activateResult.success) {
|
|
24894
25120
|
if (rawForDelegation.some((entry) => this.isRawRevocationPermissionEntry(entry)) && activateResult.status === 401 && /Cannot find parent delegation/i.test(activateResult.error ?? "")) {
|
|
24895
25121
|
throw Object.assign(
|
|
@@ -24910,6 +25136,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24910
25136
|
expiresAt,
|
|
24911
25137
|
{ siwe: prepared.siwe, signature: signature2 }
|
|
24912
25138
|
);
|
|
25139
|
+
graph.assertActive();
|
|
24913
25140
|
this.runtimePermissionGrants.push({
|
|
24914
25141
|
session: {
|
|
24915
25142
|
delegationHeader: delegatedSession.delegationHeader,
|
|
@@ -26373,6 +26600,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
26373
26600
|
* @returns A DelegatedAccess instance for performing operations
|
|
26374
26601
|
*/
|
|
26375
26602
|
async useDelegation(delegation) {
|
|
26603
|
+
const graph = this._serviceGraph;
|
|
26376
26604
|
const delegationHeader = delegation.delegationHeader;
|
|
26377
26605
|
const targetHost = delegation.host ?? this.config.host;
|
|
26378
26606
|
if (this.isSessionOnly) {
|
|
@@ -26414,7 +26642,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
26414
26642
|
targetHost,
|
|
26415
26643
|
this.wasmBindings.invoke,
|
|
26416
26644
|
this.wasmBindings.invokeAny,
|
|
26417
|
-
this.config.telemetry
|
|
26645
|
+
this.config.telemetry,
|
|
26646
|
+
graph
|
|
26418
26647
|
);
|
|
26419
26648
|
}
|
|
26420
26649
|
const mySession = this.auth?.tinyCloudSession;
|
|
@@ -26438,14 +26667,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
26438
26667
|
...Object.keys(rawAbilities).length > 0 ? { rawAbilities } : {}
|
|
26439
26668
|
});
|
|
26440
26669
|
const signature2 = await this.signer.signMessage(prepared.siwe);
|
|
26670
|
+
graph.assertActive();
|
|
26441
26671
|
const invokerSession = this.wasmBindings.completeSessionSetup({
|
|
26442
26672
|
...prepared,
|
|
26443
26673
|
signature: signature2
|
|
26444
26674
|
});
|
|
26445
26675
|
const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
|
|
26446
26676
|
targetHost,
|
|
26447
|
-
invokerSession.delegationHeader
|
|
26448
|
-
|
|
26677
|
+
invokerSession.delegationHeader,
|
|
26678
|
+
graph.signal
|
|
26679
|
+
).catch((error) => {
|
|
26680
|
+
graph.assertActive();
|
|
26681
|
+
throw error;
|
|
26682
|
+
});
|
|
26449
26683
|
if (!activateResult.success) {
|
|
26450
26684
|
throw Object.assign(
|
|
26451
26685
|
new Error(`Failed to activate delegated session: ${describeHostFailure2(activateResult)}`),
|
|
@@ -26464,6 +26698,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
26464
26698
|
siwe: prepared.siwe,
|
|
26465
26699
|
signature: signature2
|
|
26466
26700
|
};
|
|
26701
|
+
graph.assertActive();
|
|
26467
26702
|
this.trackReceivedDelegation(delegation, jwk);
|
|
26468
26703
|
this.installRuntimeGrantFromServiceSession(
|
|
26469
26704
|
delegation,
|
|
@@ -26482,7 +26717,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
26482
26717
|
targetHost,
|
|
26483
26718
|
this.wasmBindings.invoke,
|
|
26484
26719
|
this.wasmBindings.invokeAny,
|
|
26485
|
-
this.config.telemetry
|
|
26720
|
+
this.config.telemetry,
|
|
26721
|
+
graph
|
|
26486
26722
|
);
|
|
26487
26723
|
}
|
|
26488
26724
|
/**
|