@tinycloud/node-sdk 3.2.1-beta.0 → 3.2.1-beta.1
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-6_YwgSkd.d.cts → WasmKeyProvider-DRlOpvpG.d.cts} +56 -13
- package/dist/{WasmKeyProvider-6_YwgSkd.d.ts → WasmKeyProvider-DRlOpvpG.d.ts} +56 -13
- package/dist/core.cjs +131 -31
- 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 +131 -31
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +130 -30
- 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 +130 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -337,6 +337,11 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
337
337
|
*/
|
|
338
338
|
private _nodeInfoIdentity?;
|
|
339
339
|
private _lastActivationSkippedSpaceIds;
|
|
340
|
+
/**
|
|
341
|
+
* Spaces the sign-in activation reported hosted. Only the first POST of a
|
|
342
|
+
* delegation lists them: the node answers a repeat with empty lists.
|
|
343
|
+
*/
|
|
344
|
+
private _lastActivationActivatedSpaceIds;
|
|
340
345
|
constructor(config: NodeUserAuthorizationConfig);
|
|
341
346
|
/**
|
|
342
347
|
* Return the manifest currently driving sign-in behavior, or
|
|
@@ -414,6 +419,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
414
419
|
*/
|
|
415
420
|
nodeIdForHost(host: string): string | undefined;
|
|
416
421
|
get lastActivationSkippedSpaceIds(): string[];
|
|
422
|
+
get lastActivationActivatedSpaceIds(): string[];
|
|
417
423
|
/**
|
|
418
424
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
419
425
|
* see at sign-in time.
|
|
@@ -1479,9 +1485,25 @@ declare class TinyCloudNode {
|
|
|
1479
1485
|
* hosting is confirmed against the session that was active at the time.
|
|
1480
1486
|
*/
|
|
1481
1487
|
private readonly confirmedHostedSpaceIds;
|
|
1488
|
+
/**
|
|
1489
|
+
* Owned space ids known to be hosted for the current session: the sign-in
|
|
1490
|
+
* activation listed them as `activated`, or this session hosted them. Unlike
|
|
1491
|
+
* {@link confirmedHostedSpaceIds}, nothing here is inferred from a space being
|
|
1492
|
+
* merely absent from `skipped`. Read by {@link ensureOwnedSpaceHosted}.
|
|
1493
|
+
*/
|
|
1494
|
+
private readonly hostedOwnedSpaceIds;
|
|
1495
|
+
/**
|
|
1496
|
+
* In-flight host delegations, so concurrent callers share one approval per
|
|
1497
|
+
* space. `waiters` counts callers still waiting; the request is cancelled
|
|
1498
|
+
* once every caller with a signal has aborted and none waits without one.
|
|
1499
|
+
*/
|
|
1500
|
+
private readonly ownedSpaceHosts;
|
|
1482
1501
|
/** Serializes account-registry writes for the active node instance. */
|
|
1483
1502
|
private accountRegistryTail;
|
|
1484
|
-
/**
|
|
1503
|
+
/**
|
|
1504
|
+
* Hang guard for the background registry sync. It is off the sign-in path,
|
|
1505
|
+
* so it must outlast a slow but healthy sync (9–18 s on prod 1.20.2, TC-998).
|
|
1506
|
+
*/
|
|
1485
1507
|
private accountRegistryDeadlineMs;
|
|
1486
1508
|
private pendingAccountRegistrySync?;
|
|
1487
1509
|
/**
|
|
@@ -1691,6 +1713,15 @@ declare class TinyCloudNode {
|
|
|
1691
1713
|
* @param options - Optional per-call SIWE overrides for this sign-in only
|
|
1692
1714
|
*/
|
|
1693
1715
|
signIn(options?: SignInOptions): Promise<void>;
|
|
1716
|
+
/**
|
|
1717
|
+
* Wait for the account-registry sync that {@link signIn} starts in the
|
|
1718
|
+
* background (account index, this app's manifest record, space list).
|
|
1719
|
+
* Resolves once it has finished, failed or hit its hang guard; it never
|
|
1720
|
+
* rejects, and failures are logged as warnings. `signIn()` does not wait for
|
|
1721
|
+
* it, so call this only when you need the registry written, or before a first
|
|
1722
|
+
* write against a SQLite-backed node older than 1.20.2 (TC-899).
|
|
1723
|
+
*/
|
|
1724
|
+
waitForAccountRegistrySync(): Promise<void>;
|
|
1694
1725
|
private ownedSpaceId;
|
|
1695
1726
|
private bootstrapAccountIfNeeded;
|
|
1696
1727
|
private resolveBootstrapDecision;
|
|
@@ -1811,23 +1842,35 @@ declare class TinyCloudNode {
|
|
|
1811
1842
|
* registered on the node.
|
|
1812
1843
|
*
|
|
1813
1844
|
* Calling this resolves `name` to the owner's owned-space URI
|
|
1814
|
-
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It
|
|
1815
|
-
*
|
|
1816
|
-
*
|
|
1817
|
-
* already
|
|
1818
|
-
*
|
|
1819
|
-
*
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
1822
|
-
*
|
|
1823
|
-
*
|
|
1824
|
-
*
|
|
1825
|
-
*
|
|
1845
|
+
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It returns WITHOUT
|
|
1846
|
+
* submitting a host delegation when the space is known to be hosted: the
|
|
1847
|
+
* sign-in activation listed it as `activated` (any space the session's recap
|
|
1848
|
+
* covers), this session already hosted it, or the account-space spaces
|
|
1849
|
+
* registry (`account/spaces/{space_id}`, the canonical KV source of truth,
|
|
1850
|
+
* fronted by a best-effort SQLite index) has its record. Otherwise it falls
|
|
1851
|
+
* through to {@link hostOwnedSpace}, which asks for a signature; a host
|
|
1852
|
+
* already in flight for the same space (e.g. from the background registry
|
|
1853
|
+
* sync) is shared rather than asked for twice.
|
|
1854
|
+
*
|
|
1855
|
+
* Hosting is still needed when the space really isn't hosted, or when the
|
|
1856
|
+
* session's recap doesn't cover it and the registry has no record; the host
|
|
1857
|
+
* SIWE is idempotent server-side. Must be called after {@link signIn}.
|
|
1826
1858
|
*
|
|
1827
1859
|
* @param name - The owned space name (e.g. `"secrets"`).
|
|
1828
1860
|
* @returns The hosted owned-space URI.
|
|
1829
1861
|
*/
|
|
1830
1862
|
ensureOwnedSpaceHosted(name: string): Promise<string>;
|
|
1863
|
+
/**
|
|
1864
|
+
* Submit the host delegation for an owned space, sharing one in-flight
|
|
1865
|
+
* request (and so one approval) between concurrent callers in this session,
|
|
1866
|
+
* such as the background registry sync and {@link ensureOwnedSpaceHosted}.
|
|
1867
|
+
* Each caller's `signal` releases only its own wait; the request itself is
|
|
1868
|
+
* cancelled once no caller is left waiting, or when the session is replaced
|
|
1869
|
+
* ({@link cancelOwnedSpaceHosts}), so a late approval is discarded.
|
|
1870
|
+
*/
|
|
1871
|
+
private hostOwnedSpaceOnce;
|
|
1872
|
+
/** Session replacement: cancel the replaced session's in-flight hosts and forget them. */
|
|
1873
|
+
private cancelOwnedSpaceHosts;
|
|
1831
1874
|
/** Resolve and authenticate the owner encoded by an owned-space URI. */
|
|
1832
1875
|
credentialSpaceOwnerDid(spaceId: string): string;
|
|
1833
1876
|
/**
|
|
@@ -337,6 +337,11 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
337
337
|
*/
|
|
338
338
|
private _nodeInfoIdentity?;
|
|
339
339
|
private _lastActivationSkippedSpaceIds;
|
|
340
|
+
/**
|
|
341
|
+
* Spaces the sign-in activation reported hosted. Only the first POST of a
|
|
342
|
+
* delegation lists them: the node answers a repeat with empty lists.
|
|
343
|
+
*/
|
|
344
|
+
private _lastActivationActivatedSpaceIds;
|
|
340
345
|
constructor(config: NodeUserAuthorizationConfig);
|
|
341
346
|
/**
|
|
342
347
|
* Return the manifest currently driving sign-in behavior, or
|
|
@@ -414,6 +419,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
414
419
|
*/
|
|
415
420
|
nodeIdForHost(host: string): string | undefined;
|
|
416
421
|
get lastActivationSkippedSpaceIds(): string[];
|
|
422
|
+
get lastActivationActivatedSpaceIds(): string[];
|
|
417
423
|
/**
|
|
418
424
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
419
425
|
* see at sign-in time.
|
|
@@ -1479,9 +1485,25 @@ declare class TinyCloudNode {
|
|
|
1479
1485
|
* hosting is confirmed against the session that was active at the time.
|
|
1480
1486
|
*/
|
|
1481
1487
|
private readonly confirmedHostedSpaceIds;
|
|
1488
|
+
/**
|
|
1489
|
+
* Owned space ids known to be hosted for the current session: the sign-in
|
|
1490
|
+
* activation listed them as `activated`, or this session hosted them. Unlike
|
|
1491
|
+
* {@link confirmedHostedSpaceIds}, nothing here is inferred from a space being
|
|
1492
|
+
* merely absent from `skipped`. Read by {@link ensureOwnedSpaceHosted}.
|
|
1493
|
+
*/
|
|
1494
|
+
private readonly hostedOwnedSpaceIds;
|
|
1495
|
+
/**
|
|
1496
|
+
* In-flight host delegations, so concurrent callers share one approval per
|
|
1497
|
+
* space. `waiters` counts callers still waiting; the request is cancelled
|
|
1498
|
+
* once every caller with a signal has aborted and none waits without one.
|
|
1499
|
+
*/
|
|
1500
|
+
private readonly ownedSpaceHosts;
|
|
1482
1501
|
/** Serializes account-registry writes for the active node instance. */
|
|
1483
1502
|
private accountRegistryTail;
|
|
1484
|
-
/**
|
|
1503
|
+
/**
|
|
1504
|
+
* Hang guard for the background registry sync. It is off the sign-in path,
|
|
1505
|
+
* so it must outlast a slow but healthy sync (9–18 s on prod 1.20.2, TC-998).
|
|
1506
|
+
*/
|
|
1485
1507
|
private accountRegistryDeadlineMs;
|
|
1486
1508
|
private pendingAccountRegistrySync?;
|
|
1487
1509
|
/**
|
|
@@ -1691,6 +1713,15 @@ declare class TinyCloudNode {
|
|
|
1691
1713
|
* @param options - Optional per-call SIWE overrides for this sign-in only
|
|
1692
1714
|
*/
|
|
1693
1715
|
signIn(options?: SignInOptions): Promise<void>;
|
|
1716
|
+
/**
|
|
1717
|
+
* Wait for the account-registry sync that {@link signIn} starts in the
|
|
1718
|
+
* background (account index, this app's manifest record, space list).
|
|
1719
|
+
* Resolves once it has finished, failed or hit its hang guard; it never
|
|
1720
|
+
* rejects, and failures are logged as warnings. `signIn()` does not wait for
|
|
1721
|
+
* it, so call this only when you need the registry written, or before a first
|
|
1722
|
+
* write against a SQLite-backed node older than 1.20.2 (TC-899).
|
|
1723
|
+
*/
|
|
1724
|
+
waitForAccountRegistrySync(): Promise<void>;
|
|
1694
1725
|
private ownedSpaceId;
|
|
1695
1726
|
private bootstrapAccountIfNeeded;
|
|
1696
1727
|
private resolveBootstrapDecision;
|
|
@@ -1811,23 +1842,35 @@ declare class TinyCloudNode {
|
|
|
1811
1842
|
* registered on the node.
|
|
1812
1843
|
*
|
|
1813
1844
|
* Calling this resolves `name` to the owner's owned-space URI
|
|
1814
|
-
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It
|
|
1815
|
-
*
|
|
1816
|
-
*
|
|
1817
|
-
* already
|
|
1818
|
-
*
|
|
1819
|
-
*
|
|
1820
|
-
*
|
|
1821
|
-
*
|
|
1822
|
-
*
|
|
1823
|
-
*
|
|
1824
|
-
*
|
|
1825
|
-
*
|
|
1845
|
+
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It returns WITHOUT
|
|
1846
|
+
* submitting a host delegation when the space is known to be hosted: the
|
|
1847
|
+
* sign-in activation listed it as `activated` (any space the session's recap
|
|
1848
|
+
* covers), this session already hosted it, or the account-space spaces
|
|
1849
|
+
* registry (`account/spaces/{space_id}`, the canonical KV source of truth,
|
|
1850
|
+
* fronted by a best-effort SQLite index) has its record. Otherwise it falls
|
|
1851
|
+
* through to {@link hostOwnedSpace}, which asks for a signature; a host
|
|
1852
|
+
* already in flight for the same space (e.g. from the background registry
|
|
1853
|
+
* sync) is shared rather than asked for twice.
|
|
1854
|
+
*
|
|
1855
|
+
* Hosting is still needed when the space really isn't hosted, or when the
|
|
1856
|
+
* session's recap doesn't cover it and the registry has no record; the host
|
|
1857
|
+
* SIWE is idempotent server-side. Must be called after {@link signIn}.
|
|
1826
1858
|
*
|
|
1827
1859
|
* @param name - The owned space name (e.g. `"secrets"`).
|
|
1828
1860
|
* @returns The hosted owned-space URI.
|
|
1829
1861
|
*/
|
|
1830
1862
|
ensureOwnedSpaceHosted(name: string): Promise<string>;
|
|
1863
|
+
/**
|
|
1864
|
+
* Submit the host delegation for an owned space, sharing one in-flight
|
|
1865
|
+
* request (and so one approval) between concurrent callers in this session,
|
|
1866
|
+
* such as the background registry sync and {@link ensureOwnedSpaceHosted}.
|
|
1867
|
+
* Each caller's `signal` releases only its own wait; the request itself is
|
|
1868
|
+
* cancelled once no caller is left waiting, or when the session is replaced
|
|
1869
|
+
* ({@link cancelOwnedSpaceHosts}), so a late approval is discarded.
|
|
1870
|
+
*/
|
|
1871
|
+
private hostOwnedSpaceOnce;
|
|
1872
|
+
/** Session replacement: cancel the replaced session's in-flight hosts and forget them. */
|
|
1873
|
+
private cancelOwnedSpaceHosts;
|
|
1831
1874
|
/** Resolve and authenticate the owner encoded by an owned-space URI. */
|
|
1832
1875
|
credentialSpaceOwnerDid(spaceId: string): string;
|
|
1833
1876
|
/**
|
package/dist/core.cjs
CHANGED
|
@@ -462,6 +462,11 @@ var NodeUserAuthorization = class {
|
|
|
462
462
|
this._nodeFeatures = [];
|
|
463
463
|
this._nodeFeaturesKnown = false;
|
|
464
464
|
this._lastActivationSkippedSpaceIds = [];
|
|
465
|
+
/**
|
|
466
|
+
* Spaces the sign-in activation reported hosted. Only the first POST of a
|
|
467
|
+
* delegation lists them: the node answers a repeat with empty lists.
|
|
468
|
+
*/
|
|
469
|
+
this._lastActivationActivatedSpaceIds = [];
|
|
465
470
|
this.wasm = config.wasmBindings;
|
|
466
471
|
this.signer = config.signer;
|
|
467
472
|
this.signStrategy = config.signStrategy ?? defaultSignStrategy;
|
|
@@ -591,6 +596,7 @@ var NodeUserAuthorization = class {
|
|
|
591
596
|
this._nodeInfoIdentity = void 0;
|
|
592
597
|
this.tinycloudHosts = hosts && hosts.length > 0 ? [...hosts] : void 0;
|
|
593
598
|
this._lastActivationSkippedSpaceIds = [];
|
|
599
|
+
this._lastActivationActivatedSpaceIds = [];
|
|
594
600
|
if (!session) {
|
|
595
601
|
this._session = void 0;
|
|
596
602
|
this._tinyCloudSession = void 0;
|
|
@@ -685,6 +691,9 @@ var NodeUserAuthorization = class {
|
|
|
685
691
|
get lastActivationSkippedSpaceIds() {
|
|
686
692
|
return [...this._lastActivationSkippedSpaceIds];
|
|
687
693
|
}
|
|
694
|
+
get lastActivationActivatedSpaceIds() {
|
|
695
|
+
return [...this._lastActivationActivatedSpaceIds];
|
|
696
|
+
}
|
|
688
697
|
/**
|
|
689
698
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
690
699
|
* see at sign-in time.
|
|
@@ -1180,8 +1189,10 @@ var NodeUserAuthorization = class {
|
|
|
1180
1189
|
recordActivationSkippedSpaces(result, primarySpaceId) {
|
|
1181
1190
|
if (result.success) {
|
|
1182
1191
|
this._lastActivationSkippedSpaceIds = result.skipped ?? [];
|
|
1192
|
+
this._lastActivationActivatedSpaceIds = result.activated ?? [];
|
|
1183
1193
|
return;
|
|
1184
1194
|
}
|
|
1195
|
+
this._lastActivationActivatedSpaceIds = [];
|
|
1185
1196
|
this._lastActivationSkippedSpaceIds = result.status === 404 ? [primarySpaceId] : [];
|
|
1186
1197
|
}
|
|
1187
1198
|
async createBootstrapSession(options) {
|
|
@@ -3433,10 +3444,26 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3433
3444
|
* hosting is confirmed against the session that was active at the time.
|
|
3434
3445
|
*/
|
|
3435
3446
|
this.confirmedHostedSpaceIds = /* @__PURE__ */ new Set();
|
|
3447
|
+
/**
|
|
3448
|
+
* Owned space ids known to be hosted for the current session: the sign-in
|
|
3449
|
+
* activation listed them as `activated`, or this session hosted them. Unlike
|
|
3450
|
+
* {@link confirmedHostedSpaceIds}, nothing here is inferred from a space being
|
|
3451
|
+
* merely absent from `skipped`. Read by {@link ensureOwnedSpaceHosted}.
|
|
3452
|
+
*/
|
|
3453
|
+
this.hostedOwnedSpaceIds = /* @__PURE__ */ new Set();
|
|
3454
|
+
/**
|
|
3455
|
+
* In-flight host delegations, so concurrent callers share one approval per
|
|
3456
|
+
* space. `waiters` counts callers still waiting; the request is cancelled
|
|
3457
|
+
* once every caller with a signal has aborted and none waits without one.
|
|
3458
|
+
*/
|
|
3459
|
+
this.ownedSpaceHosts = /* @__PURE__ */ new Map();
|
|
3436
3460
|
/** Serializes account-registry writes for the active node instance. */
|
|
3437
3461
|
this.accountRegistryTail = Promise.resolve();
|
|
3438
|
-
/**
|
|
3439
|
-
|
|
3462
|
+
/**
|
|
3463
|
+
* Hang guard for the background registry sync. It is off the sign-in path,
|
|
3464
|
+
* so it must outlast a slow but healthy sync (9–18 s on prod 1.20.2, TC-998).
|
|
3465
|
+
*/
|
|
3466
|
+
this.accountRegistryDeadlineMs = 3e4;
|
|
3440
3467
|
/**
|
|
3441
3468
|
* True when the last signIn() detected an interactive signer and skipped
|
|
3442
3469
|
* client-side bootstrap. Apps can read this to know whether bootstrap was
|
|
@@ -4031,6 +4058,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4031
4058
|
"Cannot signIn() in session-only mode. Provide a privateKey in config to create your own space."
|
|
4032
4059
|
);
|
|
4033
4060
|
}
|
|
4061
|
+
this.pendingAccountRegistrySync?.controller.abort();
|
|
4034
4062
|
await this.accountRegistryTail;
|
|
4035
4063
|
await this.wasmBindings.ensureInitialized?.();
|
|
4036
4064
|
const address = (0, import_sdk_core10.canonicalizeAddress)(await this.signer.getAddress());
|
|
@@ -4051,8 +4079,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4051
4079
|
this._serviceContext = void 0;
|
|
4052
4080
|
this.runtimePermissionGrants = [];
|
|
4053
4081
|
this.confirmedHostedSpaceIds.clear();
|
|
4082
|
+
this.hostedOwnedSpaceIds.clear();
|
|
4054
4083
|
await this.tc.signIn(options);
|
|
4084
|
+
this.cancelOwnedSpaceHosts();
|
|
4055
4085
|
this.syncResolvedHostFromAuth();
|
|
4086
|
+
for (const spaceId of this.auth.lastActivationActivatedSpaceIds ?? []) {
|
|
4087
|
+
this.hostedOwnedSpaceIds.add(spaceId);
|
|
4088
|
+
}
|
|
4056
4089
|
this.replicationDelegateSession = void 0;
|
|
4057
4090
|
this.replicationScopeError = void 0;
|
|
4058
4091
|
if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
|
|
@@ -4077,10 +4110,20 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4077
4110
|
}
|
|
4078
4111
|
if (!bootstrapped) {
|
|
4079
4112
|
this.scheduleAccountRegistrySync();
|
|
4080
|
-
await this.accountRegistryTail;
|
|
4081
4113
|
}
|
|
4082
4114
|
this.notificationHandler.success("Successfully signed in");
|
|
4083
4115
|
}
|
|
4116
|
+
/**
|
|
4117
|
+
* Wait for the account-registry sync that {@link signIn} starts in the
|
|
4118
|
+
* background (account index, this app's manifest record, space list).
|
|
4119
|
+
* Resolves once it has finished, failed or hit its hang guard; it never
|
|
4120
|
+
* rejects, and failures are logged as warnings. `signIn()` does not wait for
|
|
4121
|
+
* it, so call this only when you need the registry written, or before a first
|
|
4122
|
+
* write against a SQLite-backed node older than 1.20.2 (TC-899).
|
|
4123
|
+
*/
|
|
4124
|
+
async waitForAccountRegistrySync() {
|
|
4125
|
+
await this.accountRegistryTail;
|
|
4126
|
+
}
|
|
4084
4127
|
ownedSpaceId(name) {
|
|
4085
4128
|
if (!this._address) {
|
|
4086
4129
|
throw new Error("Cannot resolve owned space before sign-in");
|
|
@@ -4686,17 +4729,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4686
4729
|
clearTimeout(deadline);
|
|
4687
4730
|
}
|
|
4688
4731
|
});
|
|
4689
|
-
this.pendingAccountRegistrySync = { session, promise };
|
|
4690
|
-
const
|
|
4732
|
+
this.pendingAccountRegistrySync = { session, promise, controller };
|
|
4733
|
+
const settle = () => {
|
|
4734
|
+
clearTimeout(deadline);
|
|
4691
4735
|
if (this.pendingAccountRegistrySync?.promise === promise) {
|
|
4692
4736
|
this.pendingAccountRegistrySync = void 0;
|
|
4693
4737
|
}
|
|
4694
4738
|
};
|
|
4695
|
-
void promise.then(
|
|
4696
|
-
|
|
4697
|
-
(
|
|
4698
|
-
|
|
4699
|
-
);
|
|
4739
|
+
void promise.then(settle, (error) => {
|
|
4740
|
+
settle();
|
|
4741
|
+
console.warn("TinyCloud account registry sync failed", error);
|
|
4742
|
+
});
|
|
4700
4743
|
}
|
|
4701
4744
|
enqueueAccountRegistryOperation(session, task) {
|
|
4702
4745
|
const operation = this.accountRegistryTail.then(async () => {
|
|
@@ -4734,10 +4777,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4734
4777
|
}
|
|
4735
4778
|
async withAccountRegistryRetry(task, signal) {
|
|
4736
4779
|
const delays = [250, 1e3, 3e3];
|
|
4780
|
+
const stopped = (detail) => {
|
|
4781
|
+
if (signal.reason instanceof DOMException && signal.reason.name === "TimeoutError") {
|
|
4782
|
+
console.warn("TinyCloud account registry sync stopped: deadline exceeded", detail);
|
|
4783
|
+
}
|
|
4784
|
+
};
|
|
4737
4785
|
let lastError;
|
|
4738
4786
|
for (let attempt = 0; attempt < delays.length; attempt += 1) {
|
|
4739
4787
|
if (signal.aborted) {
|
|
4740
|
-
|
|
4788
|
+
stopped(signal.reason);
|
|
4741
4789
|
return;
|
|
4742
4790
|
}
|
|
4743
4791
|
try {
|
|
@@ -4745,7 +4793,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4745
4793
|
return;
|
|
4746
4794
|
} catch (error) {
|
|
4747
4795
|
if (signal.aborted) {
|
|
4748
|
-
|
|
4796
|
+
stopped(error);
|
|
4749
4797
|
return;
|
|
4750
4798
|
}
|
|
4751
4799
|
const verdict = (0, import_sdk_core10.authorizationVerdictOf)(error);
|
|
@@ -4838,7 +4886,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4838
4886
|
if (!session) {
|
|
4839
4887
|
throw new Error("Owned space hosting requires an active session");
|
|
4840
4888
|
}
|
|
4841
|
-
if (this.confirmedHostedSpaceIds.has(spaceId)) {
|
|
4889
|
+
if (this.confirmedHostedSpaceIds.has(spaceId) || this.hostedOwnedSpaceIds.has(spaceId)) {
|
|
4842
4890
|
return;
|
|
4843
4891
|
}
|
|
4844
4892
|
const host = this.hosts[0] ?? this.config.host;
|
|
@@ -4856,8 +4904,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4856
4904
|
{ cause: activation }
|
|
4857
4905
|
);
|
|
4858
4906
|
}
|
|
4859
|
-
const
|
|
4860
|
-
const created = signal ? await authorization.hostOwnedSpaceResult(spaceId, void 0, signal) : await authorization.hostOwnedSpaceResult(spaceId);
|
|
4907
|
+
const created = await this.hostOwnedSpaceOnce(spaceId, signal);
|
|
4861
4908
|
if (!created.success) {
|
|
4862
4909
|
throw Object.assign(
|
|
4863
4910
|
new Error(`Failed to create owned space ${spaceId}: ${describeHostFailure2(created)}`),
|
|
@@ -4874,7 +4921,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4874
4921
|
{ cause: retry }
|
|
4875
4922
|
);
|
|
4876
4923
|
}
|
|
4877
|
-
this.
|
|
4924
|
+
if (this.auth.tinyCloudSession === session) {
|
|
4925
|
+
this.confirmedHostedSpaceIds.add(spaceId);
|
|
4926
|
+
this.hostedOwnedSpaceIds.add(spaceId);
|
|
4927
|
+
}
|
|
4878
4928
|
}
|
|
4879
4929
|
/**
|
|
4880
4930
|
* Host one of this user's owned spaces by name (e.g. `"applications"`).
|
|
@@ -4906,7 +4956,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4906
4956
|
if (!host) {
|
|
4907
4957
|
throw new Error("Owned space hosting requires a TinyCloud host");
|
|
4908
4958
|
}
|
|
4909
|
-
const hosted = await this.
|
|
4959
|
+
const hosted = await this.hostOwnedSpaceOnce(spaceId);
|
|
4910
4960
|
if (!hosted.success) {
|
|
4911
4961
|
throw Object.assign(
|
|
4912
4962
|
new Error(`Failed to host owned space ${spaceId}: ${describeHostFailure2(hosted)}`),
|
|
@@ -4925,6 +4975,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4925
4975
|
{ cause: activation }
|
|
4926
4976
|
);
|
|
4927
4977
|
}
|
|
4978
|
+
if (this.auth?.tinyCloudSession === session) this.hostedOwnedSpaceIds.add(spaceId);
|
|
4928
4979
|
try {
|
|
4929
4980
|
await this.enqueueAccountRegistryOperation(session, async () => {
|
|
4930
4981
|
await this.account.spaces.register({
|
|
@@ -4952,18 +5003,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4952
5003
|
* registered on the node.
|
|
4953
5004
|
*
|
|
4954
5005
|
* Calling this resolves `name` to the owner's owned-space URI
|
|
4955
|
-
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It
|
|
4956
|
-
*
|
|
4957
|
-
*
|
|
4958
|
-
* already
|
|
4959
|
-
*
|
|
4960
|
-
*
|
|
4961
|
-
*
|
|
4962
|
-
*
|
|
4963
|
-
*
|
|
4964
|
-
*
|
|
4965
|
-
*
|
|
4966
|
-
*
|
|
5006
|
+
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It returns WITHOUT
|
|
5007
|
+
* submitting a host delegation when the space is known to be hosted: the
|
|
5008
|
+
* sign-in activation listed it as `activated` (any space the session's recap
|
|
5009
|
+
* covers), this session already hosted it, or the account-space spaces
|
|
5010
|
+
* registry (`account/spaces/{space_id}`, the canonical KV source of truth,
|
|
5011
|
+
* fronted by a best-effort SQLite index) has its record. Otherwise it falls
|
|
5012
|
+
* through to {@link hostOwnedSpace}, which asks for a signature; a host
|
|
5013
|
+
* already in flight for the same space (e.g. from the background registry
|
|
5014
|
+
* sync) is shared rather than asked for twice.
|
|
5015
|
+
*
|
|
5016
|
+
* Hosting is still needed when the space really isn't hosted, or when the
|
|
5017
|
+
* session's recap doesn't cover it and the registry has no record; the host
|
|
5018
|
+
* SIWE is idempotent server-side. Must be called after {@link signIn}.
|
|
4967
5019
|
*
|
|
4968
5020
|
* @param name - The owned space name (e.g. `"secrets"`).
|
|
4969
5021
|
* @returns The hosted owned-space URI.
|
|
@@ -4972,13 +5024,57 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4972
5024
|
if (!this.auth || !this.auth.tinyCloudSession) {
|
|
4973
5025
|
throw new Error("Not signed in. Call signIn() first.");
|
|
4974
5026
|
}
|
|
4975
|
-
await this.accountRegistryTail;
|
|
4976
5027
|
const spaceId = this.ownedSpaceId(name);
|
|
4977
|
-
if (await this.isOwnedSpaceRegistered(spaceId)) {
|
|
5028
|
+
if (this.hostedOwnedSpaceIds.has(spaceId) || await this.isOwnedSpaceRegistered(spaceId)) {
|
|
4978
5029
|
return spaceId;
|
|
4979
5030
|
}
|
|
4980
5031
|
return this.hostOwnedSpace(name);
|
|
4981
5032
|
}
|
|
5033
|
+
/**
|
|
5034
|
+
* Submit the host delegation for an owned space, sharing one in-flight
|
|
5035
|
+
* request (and so one approval) between concurrent callers in this session,
|
|
5036
|
+
* such as the background registry sync and {@link ensureOwnedSpaceHosted}.
|
|
5037
|
+
* Each caller's `signal` releases only its own wait; the request itself is
|
|
5038
|
+
* cancelled once no caller is left waiting, or when the session is replaced
|
|
5039
|
+
* ({@link cancelOwnedSpaceHosts}), so a late approval is discarded.
|
|
5040
|
+
*/
|
|
5041
|
+
hostOwnedSpaceOnce(spaceId, signal) {
|
|
5042
|
+
if (signal?.aborted) return Promise.reject(signal.reason);
|
|
5043
|
+
let entry = this.ownedSpaceHosts.get(spaceId);
|
|
5044
|
+
if (!entry) {
|
|
5045
|
+
const controller = new AbortController();
|
|
5046
|
+
const promise = this.auth.hostOwnedSpaceResult(spaceId, void 0, controller.signal);
|
|
5047
|
+
const created = { promise, controller, waiters: 0 };
|
|
5048
|
+
this.ownedSpaceHosts.set(spaceId, created);
|
|
5049
|
+
const forget = () => {
|
|
5050
|
+
if (this.ownedSpaceHosts.get(spaceId) === created) this.ownedSpaceHosts.delete(spaceId);
|
|
5051
|
+
};
|
|
5052
|
+
promise.then(forget, forget);
|
|
5053
|
+
entry = created;
|
|
5054
|
+
}
|
|
5055
|
+
if (!signal) {
|
|
5056
|
+
entry.waiters = Number.POSITIVE_INFINITY;
|
|
5057
|
+
return entry.promise;
|
|
5058
|
+
}
|
|
5059
|
+
entry.waiters += 1;
|
|
5060
|
+
const shared = entry;
|
|
5061
|
+
return new Promise((resolve, reject2) => {
|
|
5062
|
+
const onAbort = () => {
|
|
5063
|
+
reject2(signal.reason);
|
|
5064
|
+
shared.waiters -= 1;
|
|
5065
|
+
if (shared.waiters !== 0) return;
|
|
5066
|
+
shared.controller.abort(signal.reason);
|
|
5067
|
+
if (this.ownedSpaceHosts.get(spaceId) === shared) this.ownedSpaceHosts.delete(spaceId);
|
|
5068
|
+
};
|
|
5069
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
5070
|
+
shared.promise.then(resolve, reject2).finally(() => signal.removeEventListener("abort", onAbort));
|
|
5071
|
+
});
|
|
5072
|
+
}
|
|
5073
|
+
/** Session replacement: cancel the replaced session's in-flight hosts and forget them. */
|
|
5074
|
+
cancelOwnedSpaceHosts() {
|
|
5075
|
+
for (const { controller } of this.ownedSpaceHosts.values()) controller.abort();
|
|
5076
|
+
this.ownedSpaceHosts.clear();
|
|
5077
|
+
}
|
|
4982
5078
|
/** Resolve and authenticate the owner encoded by an owned-space URI. */
|
|
4983
5079
|
credentialSpaceOwnerDid(spaceId) {
|
|
4984
5080
|
const ownerDid = this.ownerDidFromSpaceId(spaceId);
|
|
@@ -5221,6 +5317,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5221
5317
|
sessionExpiry: stagedSessionExpiry,
|
|
5222
5318
|
recap: stagedRecap
|
|
5223
5319
|
});
|
|
5320
|
+
this.pendingAccountRegistrySync?.controller.abort();
|
|
5321
|
+
await this.accountRegistryTail;
|
|
5224
5322
|
const oldGraph = this._serviceGraph;
|
|
5225
5323
|
const oldCore = this.tc;
|
|
5226
5324
|
this.sessionManager = stagedManager;
|
|
@@ -5254,6 +5352,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5254
5352
|
this._recapOperationsCache = stagedPrimary.cache;
|
|
5255
5353
|
this.runtimePermissionGrants = stagedPrimary.grants;
|
|
5256
5354
|
this.confirmedHostedSpaceIds.clear();
|
|
5355
|
+
this.hostedOwnedSpaceIds.clear();
|
|
5356
|
+
this.cancelOwnedSpaceHosts();
|
|
5257
5357
|
this._restoredNodeFeatures = restoredNodeFeatures;
|
|
5258
5358
|
if (this.auth) {
|
|
5259
5359
|
this.auth.installRestoredSession(stagedManager, stagedTcSession, [stagedHost], restoredNodeFeatures);
|