@tinycloud/node-sdk 2.4.0 → 2.5.0-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/{core-DfE4s_Rg.d.cts → core-ojeY-wet.d.cts} +37 -5
- package/dist/{core-DfE4s_Rg.d.ts → core-ojeY-wet.d.ts} +37 -5
- package/dist/core.cjs +175 -37
- 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 +175 -37
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +175 -37
- 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 +175 -37
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, IWasmBindings, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignInOptions, Delegation, DelegatedResource, PermissionEntry, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, AccountService, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, ResolvedDelegate, KeyProvider, ISessionManager, JWK } from '@tinycloud/sdk-core';
|
|
1
|
+
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, IWasmBindings, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignRequest, SignInOptions, Delegation, DelegatedResource, PermissionEntry, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, AccountService, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, ResolvedDelegate, KeyProvider, ISessionManager, JWK } from '@tinycloud/sdk-core';
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { InvokeFunction, InvokeAnyFunction } from '@tinycloud/sdk-services';
|
|
4
4
|
|
|
@@ -430,7 +430,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
430
430
|
* Create a specific owned space on the server via host delegation.
|
|
431
431
|
* Used by manifest registry setup for the account space.
|
|
432
432
|
*/
|
|
433
|
-
hostOwnedSpace(spaceId: string): Promise<boolean>;
|
|
433
|
+
hostOwnedSpace(spaceId: string, purpose?: SignRequest["purpose"]): Promise<boolean>;
|
|
434
434
|
/**
|
|
435
435
|
* Ensure the user's space exists on the TinyCloud server.
|
|
436
436
|
* Creates the space if it doesn't exist and autoCreateSpace is enabled.
|
|
@@ -469,7 +469,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
469
469
|
/**
|
|
470
470
|
* Sign a message with the connected signer.
|
|
471
471
|
*/
|
|
472
|
-
signMessage(message: string): Promise<string>;
|
|
472
|
+
signMessage(message: string, purpose?: SignRequest["purpose"]): Promise<string>;
|
|
473
473
|
/**
|
|
474
474
|
* Prepare a session for external signing.
|
|
475
475
|
*
|
|
@@ -893,8 +893,8 @@ declare class TinyCloudNode {
|
|
|
893
893
|
private _hooks?;
|
|
894
894
|
private _vault?;
|
|
895
895
|
private _encryption?;
|
|
896
|
-
private _baseSecrets
|
|
897
|
-
private _secrets
|
|
896
|
+
private _baseSecrets;
|
|
897
|
+
private _secrets;
|
|
898
898
|
private _account?;
|
|
899
899
|
/** Cached public KV with proper delegation (set by ensurePublicSpace) */
|
|
900
900
|
private _publicKV?;
|
|
@@ -917,6 +917,27 @@ declare class TinyCloudNode {
|
|
|
917
917
|
* {@link currentTinyCloudSession} as a fallback for `auth.tinyCloudSession`.
|
|
918
918
|
*/
|
|
919
919
|
private _restoredTcSession?;
|
|
920
|
+
/**
|
|
921
|
+
* True when the last signIn() detected an interactive signer and skipped
|
|
922
|
+
* client-side bootstrap. Apps can read this to know whether bootstrap was
|
|
923
|
+
* deferred to the server (OpenKey) or requires a separate user action.
|
|
924
|
+
*/
|
|
925
|
+
private _bootstrapSkipped;
|
|
926
|
+
/**
|
|
927
|
+
* Outcome of the last signIn()'s account-bootstrap attempt. `skipped` is
|
|
928
|
+
* true when bootstrap did not complete (interactive signer, auto-sign
|
|
929
|
+
* denied, or a bootstrap step failed); `reason` carries the cause so apps
|
|
930
|
+
* can surface a "finish account setup" call-to-action.
|
|
931
|
+
*/
|
|
932
|
+
private _bootstrapStatus;
|
|
933
|
+
/** Whether the last signIn() skipped client-side bootstrap because the
|
|
934
|
+
* signer is interactive (browser wallet / EIP-1193 provider). */
|
|
935
|
+
get bootstrapSkipped(): boolean;
|
|
936
|
+
/** Outcome of the last signIn()'s account-bootstrap attempt. */
|
|
937
|
+
get bootstrapStatus(): {
|
|
938
|
+
skipped: boolean;
|
|
939
|
+
reason?: string;
|
|
940
|
+
};
|
|
920
941
|
private get nodeFeatures();
|
|
921
942
|
/** SIWE domain — uses config override or defaults to app.tinycloud.xyz */
|
|
922
943
|
private get siweDomain();
|
|
@@ -1013,6 +1034,11 @@ declare class TinyCloudNode {
|
|
|
1013
1034
|
* Available after signIn().
|
|
1014
1035
|
*/
|
|
1015
1036
|
get session(): TinyCloudSession | undefined;
|
|
1037
|
+
/**
|
|
1038
|
+
* Get the currently active session in the shape callers can persist and later
|
|
1039
|
+
* pass back to {@link restoreSession}.
|
|
1040
|
+
*/
|
|
1041
|
+
get restorableSession(): TinyCloudSession | undefined;
|
|
1016
1042
|
/**
|
|
1017
1043
|
* Sign in and create a new session.
|
|
1018
1044
|
* This creates the user's space if it doesn't exist.
|
|
@@ -1222,6 +1248,8 @@ declare class TinyCloudNode {
|
|
|
1222
1248
|
private initializeServices;
|
|
1223
1249
|
private createSpaceScopedKVService;
|
|
1224
1250
|
getDefaultEncryptionNetworkId(name?: string): string;
|
|
1251
|
+
getEncryptionNetworkIdForSpace(spaceId: string, name?: string): string;
|
|
1252
|
+
private ownerDidFromSpaceId;
|
|
1225
1253
|
private requireServiceSession;
|
|
1226
1254
|
private createEncryptionCrypto;
|
|
1227
1255
|
private fetchNodeId;
|
|
@@ -1327,6 +1355,10 @@ declare class TinyCloudNode {
|
|
|
1327
1355
|
* App-facing secrets API backed by the `secrets` space vault.
|
|
1328
1356
|
*/
|
|
1329
1357
|
get secrets(): ISecretsService;
|
|
1358
|
+
/**
|
|
1359
|
+
* App-facing secrets API backed by the requested space's vault.
|
|
1360
|
+
*/
|
|
1361
|
+
secretsForSpace(spaceId: string): ISecretsService;
|
|
1330
1362
|
private getBaseSecrets;
|
|
1331
1363
|
/**
|
|
1332
1364
|
* Hooks write stream subscription API.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, IWasmBindings, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignInOptions, Delegation, DelegatedResource, PermissionEntry, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, AccountService, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, ResolvedDelegate, KeyProvider, ISessionManager, JWK } from '@tinycloud/sdk-core';
|
|
1
|
+
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, IWasmBindings, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignRequest, SignInOptions, Delegation, DelegatedResource, PermissionEntry, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, AccountService, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, ResolvedDelegate, KeyProvider, ISessionManager, JWK } from '@tinycloud/sdk-core';
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { InvokeFunction, InvokeAnyFunction } from '@tinycloud/sdk-services';
|
|
4
4
|
|
|
@@ -430,7 +430,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
430
430
|
* Create a specific owned space on the server via host delegation.
|
|
431
431
|
* Used by manifest registry setup for the account space.
|
|
432
432
|
*/
|
|
433
|
-
hostOwnedSpace(spaceId: string): Promise<boolean>;
|
|
433
|
+
hostOwnedSpace(spaceId: string, purpose?: SignRequest["purpose"]): Promise<boolean>;
|
|
434
434
|
/**
|
|
435
435
|
* Ensure the user's space exists on the TinyCloud server.
|
|
436
436
|
* Creates the space if it doesn't exist and autoCreateSpace is enabled.
|
|
@@ -469,7 +469,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
469
469
|
/**
|
|
470
470
|
* Sign a message with the connected signer.
|
|
471
471
|
*/
|
|
472
|
-
signMessage(message: string): Promise<string>;
|
|
472
|
+
signMessage(message: string, purpose?: SignRequest["purpose"]): Promise<string>;
|
|
473
473
|
/**
|
|
474
474
|
* Prepare a session for external signing.
|
|
475
475
|
*
|
|
@@ -893,8 +893,8 @@ declare class TinyCloudNode {
|
|
|
893
893
|
private _hooks?;
|
|
894
894
|
private _vault?;
|
|
895
895
|
private _encryption?;
|
|
896
|
-
private _baseSecrets
|
|
897
|
-
private _secrets
|
|
896
|
+
private _baseSecrets;
|
|
897
|
+
private _secrets;
|
|
898
898
|
private _account?;
|
|
899
899
|
/** Cached public KV with proper delegation (set by ensurePublicSpace) */
|
|
900
900
|
private _publicKV?;
|
|
@@ -917,6 +917,27 @@ declare class TinyCloudNode {
|
|
|
917
917
|
* {@link currentTinyCloudSession} as a fallback for `auth.tinyCloudSession`.
|
|
918
918
|
*/
|
|
919
919
|
private _restoredTcSession?;
|
|
920
|
+
/**
|
|
921
|
+
* True when the last signIn() detected an interactive signer and skipped
|
|
922
|
+
* client-side bootstrap. Apps can read this to know whether bootstrap was
|
|
923
|
+
* deferred to the server (OpenKey) or requires a separate user action.
|
|
924
|
+
*/
|
|
925
|
+
private _bootstrapSkipped;
|
|
926
|
+
/**
|
|
927
|
+
* Outcome of the last signIn()'s account-bootstrap attempt. `skipped` is
|
|
928
|
+
* true when bootstrap did not complete (interactive signer, auto-sign
|
|
929
|
+
* denied, or a bootstrap step failed); `reason` carries the cause so apps
|
|
930
|
+
* can surface a "finish account setup" call-to-action.
|
|
931
|
+
*/
|
|
932
|
+
private _bootstrapStatus;
|
|
933
|
+
/** Whether the last signIn() skipped client-side bootstrap because the
|
|
934
|
+
* signer is interactive (browser wallet / EIP-1193 provider). */
|
|
935
|
+
get bootstrapSkipped(): boolean;
|
|
936
|
+
/** Outcome of the last signIn()'s account-bootstrap attempt. */
|
|
937
|
+
get bootstrapStatus(): {
|
|
938
|
+
skipped: boolean;
|
|
939
|
+
reason?: string;
|
|
940
|
+
};
|
|
920
941
|
private get nodeFeatures();
|
|
921
942
|
/** SIWE domain — uses config override or defaults to app.tinycloud.xyz */
|
|
922
943
|
private get siweDomain();
|
|
@@ -1013,6 +1034,11 @@ declare class TinyCloudNode {
|
|
|
1013
1034
|
* Available after signIn().
|
|
1014
1035
|
*/
|
|
1015
1036
|
get session(): TinyCloudSession | undefined;
|
|
1037
|
+
/**
|
|
1038
|
+
* Get the currently active session in the shape callers can persist and later
|
|
1039
|
+
* pass back to {@link restoreSession}.
|
|
1040
|
+
*/
|
|
1041
|
+
get restorableSession(): TinyCloudSession | undefined;
|
|
1016
1042
|
/**
|
|
1017
1043
|
* Sign in and create a new session.
|
|
1018
1044
|
* This creates the user's space if it doesn't exist.
|
|
@@ -1222,6 +1248,8 @@ declare class TinyCloudNode {
|
|
|
1222
1248
|
private initializeServices;
|
|
1223
1249
|
private createSpaceScopedKVService;
|
|
1224
1250
|
getDefaultEncryptionNetworkId(name?: string): string;
|
|
1251
|
+
getEncryptionNetworkIdForSpace(spaceId: string, name?: string): string;
|
|
1252
|
+
private ownerDidFromSpaceId;
|
|
1225
1253
|
private requireServiceSession;
|
|
1226
1254
|
private createEncryptionCrypto;
|
|
1227
1255
|
private fetchNodeId;
|
|
@@ -1327,6 +1355,10 @@ declare class TinyCloudNode {
|
|
|
1327
1355
|
* App-facing secrets API backed by the `secrets` space vault.
|
|
1328
1356
|
*/
|
|
1329
1357
|
get secrets(): ISecretsService;
|
|
1358
|
+
/**
|
|
1359
|
+
* App-facing secrets API backed by the requested space's vault.
|
|
1360
|
+
*/
|
|
1361
|
+
secretsForSpace(spaceId: string): ISecretsService;
|
|
1330
1362
|
private getBaseSecrets;
|
|
1331
1363
|
/**
|
|
1332
1364
|
* Hooks write stream subscription API.
|
package/dist/core.cjs
CHANGED
|
@@ -702,7 +702,7 @@ var NodeUserAuthorization = class {
|
|
|
702
702
|
* Create the space on the TinyCloud server (host delegation).
|
|
703
703
|
* This registers the user as the owner of the space.
|
|
704
704
|
*/
|
|
705
|
-
async hostSpace(targetSpaceId) {
|
|
705
|
+
async hostSpace(targetSpaceId, purpose) {
|
|
706
706
|
if (!this._tinyCloudSession || !this._address || !this._chainId) {
|
|
707
707
|
throw new Error("Must be signed in to host space");
|
|
708
708
|
}
|
|
@@ -718,7 +718,7 @@ var NodeUserAuthorization = class {
|
|
|
718
718
|
spaceId,
|
|
719
719
|
peerId
|
|
720
720
|
});
|
|
721
|
-
const signature = await this.signMessage(siwe);
|
|
721
|
+
const signature = await this.signMessage(siwe, purpose);
|
|
722
722
|
const headers = this.wasm.siweToDelegationHeaders({ siwe, signature });
|
|
723
723
|
const result = await (0, import_sdk_core3.submitHostDelegation)(host, headers);
|
|
724
724
|
return result.success;
|
|
@@ -734,8 +734,8 @@ var NodeUserAuthorization = class {
|
|
|
734
734
|
* Create a specific owned space on the server via host delegation.
|
|
735
735
|
* Used by manifest registry setup for the account space.
|
|
736
736
|
*/
|
|
737
|
-
async hostOwnedSpace(spaceId) {
|
|
738
|
-
return this.hostSpace(spaceId);
|
|
737
|
+
async hostOwnedSpace(spaceId, purpose) {
|
|
738
|
+
return this.hostSpace(spaceId, purpose);
|
|
739
739
|
}
|
|
740
740
|
/**
|
|
741
741
|
* Ensure the user's space exists on the TinyCloud server.
|
|
@@ -885,7 +885,8 @@ var NodeUserAuthorization = class {
|
|
|
885
885
|
address,
|
|
886
886
|
chainId,
|
|
887
887
|
message: prepared.siwe,
|
|
888
|
-
type: "siwe"
|
|
888
|
+
type: "siwe",
|
|
889
|
+
purpose: "bootstrap-session"
|
|
889
890
|
});
|
|
890
891
|
const session = this.wasm.completeSessionSetup({
|
|
891
892
|
...prepared,
|
|
@@ -949,7 +950,8 @@ var NodeUserAuthorization = class {
|
|
|
949
950
|
address,
|
|
950
951
|
chainId,
|
|
951
952
|
message: prepared.siwe,
|
|
952
|
-
type: "siwe"
|
|
953
|
+
type: "siwe",
|
|
954
|
+
purpose: "sign-in"
|
|
953
955
|
});
|
|
954
956
|
const session = this.wasm.completeSessionSetup({
|
|
955
957
|
...prepared,
|
|
@@ -1037,7 +1039,7 @@ var NodeUserAuthorization = class {
|
|
|
1037
1039
|
/**
|
|
1038
1040
|
* Sign a message with the connected signer.
|
|
1039
1041
|
*/
|
|
1040
|
-
async signMessage(message) {
|
|
1042
|
+
async signMessage(message, purpose) {
|
|
1041
1043
|
if (!this._address) {
|
|
1042
1044
|
this._address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
|
|
1043
1045
|
}
|
|
@@ -1048,7 +1050,8 @@ var NodeUserAuthorization = class {
|
|
|
1048
1050
|
address: this._address,
|
|
1049
1051
|
chainId: this._chainId,
|
|
1050
1052
|
message,
|
|
1051
|
-
type: "message"
|
|
1053
|
+
type: "message",
|
|
1054
|
+
...purpose ? { purpose } : {}
|
|
1052
1055
|
});
|
|
1053
1056
|
}
|
|
1054
1057
|
/**
|
|
@@ -1523,12 +1526,12 @@ function displayActionUrn(action) {
|
|
|
1523
1526
|
function secretActionName(action) {
|
|
1524
1527
|
return action;
|
|
1525
1528
|
}
|
|
1526
|
-
function secretPermissionEntries(name, options, action, encryptionNetworkId) {
|
|
1529
|
+
function secretPermissionEntries(name, options, action, space, encryptionNetworkId) {
|
|
1527
1530
|
const entries = [];
|
|
1528
1531
|
const path = action === "list" ? (0, import_sdk_core7.resolveSecretListPrefix)(options) : (0, import_sdk_core7.resolveSecretPath)(name, options).permissionPaths.vault;
|
|
1529
1532
|
entries.push({
|
|
1530
1533
|
service: "tinycloud.kv",
|
|
1531
|
-
space
|
|
1534
|
+
space,
|
|
1532
1535
|
path,
|
|
1533
1536
|
actions: [secretActionName(action)],
|
|
1534
1537
|
skipPrefix: true
|
|
@@ -1543,11 +1546,23 @@ function secretPermissionEntries(name, options, action, encryptionNetworkId) {
|
|
|
1543
1546
|
}
|
|
1544
1547
|
return entries;
|
|
1545
1548
|
}
|
|
1549
|
+
function normalizeSpace(space, resolveSpace) {
|
|
1550
|
+
if (!space) return void 0;
|
|
1551
|
+
if (space.startsWith("tinycloud:")) return space;
|
|
1552
|
+
return resolveSpace?.(space) ?? space;
|
|
1553
|
+
}
|
|
1554
|
+
function spaceMatches(granted, requested, resolveSpace) {
|
|
1555
|
+
if (!granted || !requested) return false;
|
|
1556
|
+
return normalizeSpace(granted, resolveSpace) === normalizeSpace(requested, resolveSpace);
|
|
1557
|
+
}
|
|
1546
1558
|
var NodeSecretsService = class {
|
|
1547
1559
|
constructor(config) {
|
|
1548
1560
|
this.config = config;
|
|
1549
1561
|
this.shouldRestoreUnlock = false;
|
|
1550
1562
|
}
|
|
1563
|
+
get space() {
|
|
1564
|
+
return this.config.space ?? SECRETS_SPACE;
|
|
1565
|
+
}
|
|
1551
1566
|
get vault() {
|
|
1552
1567
|
return this.service.vault;
|
|
1553
1568
|
}
|
|
@@ -1600,6 +1615,7 @@ var NodeSecretsService = class {
|
|
|
1600
1615
|
name,
|
|
1601
1616
|
options,
|
|
1602
1617
|
action,
|
|
1618
|
+
this.space,
|
|
1603
1619
|
action === "get" ? this.config.getEncryptionNetworkId?.() : void 0
|
|
1604
1620
|
);
|
|
1605
1621
|
} catch (error) {
|
|
@@ -1649,7 +1665,7 @@ var NodeSecretsService = class {
|
|
|
1649
1665
|
(entry) => manifests.some((candidate) => {
|
|
1650
1666
|
const resolved = (0, import_sdk_core7.resolveManifest)(candidate);
|
|
1651
1667
|
return resolved.resources.some(
|
|
1652
|
-
(resource) => resource.service === entry.service && resource.space
|
|
1668
|
+
(resource) => resource.service === entry.service && spaceMatches(resource.space, entry.space, this.config.resolveSpace) && resource.path === entry.path && entry.actions.every((action) => resource.actions.includes(action))
|
|
1653
1669
|
);
|
|
1654
1670
|
})
|
|
1655
1671
|
);
|
|
@@ -1666,6 +1682,15 @@ var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core8.EXPIRY.SESSION_MS;
|
|
|
1666
1682
|
function isOpenKeyAutoSignStrategy(strategy) {
|
|
1667
1683
|
return strategy?.openKeyAutoSign === true;
|
|
1668
1684
|
}
|
|
1685
|
+
function isInteractiveSigner(config) {
|
|
1686
|
+
if (config.privateKey) {
|
|
1687
|
+
return false;
|
|
1688
|
+
}
|
|
1689
|
+
if (isOpenKeyAutoSignStrategy(config.signStrategy)) {
|
|
1690
|
+
return false;
|
|
1691
|
+
}
|
|
1692
|
+
return config.signer !== void 0;
|
|
1693
|
+
}
|
|
1669
1694
|
function didPrincipalMatches2(actual, expected) {
|
|
1670
1695
|
try {
|
|
1671
1696
|
return (0, import_sdk_core8.principalDidEquals)(actual, expected);
|
|
@@ -1673,6 +1698,20 @@ function didPrincipalMatches2(actual, expected) {
|
|
|
1673
1698
|
return actual === expected;
|
|
1674
1699
|
}
|
|
1675
1700
|
}
|
|
1701
|
+
function sharingActionsToAbilities(path, actions) {
|
|
1702
|
+
var _a;
|
|
1703
|
+
const abilities = {};
|
|
1704
|
+
for (const action of actions) {
|
|
1705
|
+
const slash = action.indexOf("/");
|
|
1706
|
+
if (slash === -1) return void 0;
|
|
1707
|
+
const shortService = import_sdk_core8.SERVICE_LONG_TO_SHORT[action.slice(0, slash)];
|
|
1708
|
+
if (shortService === void 0) return void 0;
|
|
1709
|
+
abilities[shortService] ?? (abilities[shortService] = {});
|
|
1710
|
+
(_a = abilities[shortService])[path] ?? (_a[path] = []);
|
|
1711
|
+
abilities[shortService][path].push(action);
|
|
1712
|
+
}
|
|
1713
|
+
return Object.keys(abilities).length > 0 ? abilities : void 0;
|
|
1714
|
+
}
|
|
1676
1715
|
function base64UrlEncode(bytes) {
|
|
1677
1716
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
1678
1717
|
let output = "";
|
|
@@ -1785,7 +1824,24 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
1785
1824
|
this.auth = null;
|
|
1786
1825
|
this.tc = null;
|
|
1787
1826
|
this._chainId = 1;
|
|
1827
|
+
this._baseSecrets = /* @__PURE__ */ new Map();
|
|
1828
|
+
this._secrets = /* @__PURE__ */ new Map();
|
|
1788
1829
|
this.runtimePermissionGrants = [];
|
|
1830
|
+
/**
|
|
1831
|
+
* True when the last signIn() detected an interactive signer and skipped
|
|
1832
|
+
* client-side bootstrap. Apps can read this to know whether bootstrap was
|
|
1833
|
+
* deferred to the server (OpenKey) or requires a separate user action.
|
|
1834
|
+
*/
|
|
1835
|
+
this._bootstrapSkipped = false;
|
|
1836
|
+
/**
|
|
1837
|
+
* Outcome of the last signIn()'s account-bootstrap attempt. `skipped` is
|
|
1838
|
+
* true when bootstrap did not complete (interactive signer, auto-sign
|
|
1839
|
+
* denied, or a bootstrap step failed); `reason` carries the cause so apps
|
|
1840
|
+
* can surface a "finish account setup" call-to-action.
|
|
1841
|
+
*/
|
|
1842
|
+
this._bootstrapStatus = {
|
|
1843
|
+
skipped: false
|
|
1844
|
+
};
|
|
1789
1845
|
this.invokeWithRuntimePermissions = (session, service, path, action, facts) => {
|
|
1790
1846
|
return this.wasmBindings.invoke(
|
|
1791
1847
|
this.selectInvocationSession(session, service, path, action),
|
|
@@ -1878,6 +1934,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
1878
1934
|
static registerNodeDefaults(defaults) {
|
|
1879
1935
|
_TinyCloudNode.nodeDefaults = defaults;
|
|
1880
1936
|
}
|
|
1937
|
+
/** Whether the last signIn() skipped client-side bootstrap because the
|
|
1938
|
+
* signer is interactive (browser wallet / EIP-1193 provider). */
|
|
1939
|
+
get bootstrapSkipped() {
|
|
1940
|
+
return this._bootstrapSkipped;
|
|
1941
|
+
}
|
|
1942
|
+
/** Outcome of the last signIn()'s account-bootstrap attempt. */
|
|
1943
|
+
get bootstrapStatus() {
|
|
1944
|
+
return this._bootstrapStatus;
|
|
1945
|
+
}
|
|
1881
1946
|
get nodeFeatures() {
|
|
1882
1947
|
return this.auth?.nodeFeatures ?? [];
|
|
1883
1948
|
}
|
|
@@ -2047,6 +2112,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2047
2112
|
get session() {
|
|
2048
2113
|
return this.auth?.tinyCloudSession;
|
|
2049
2114
|
}
|
|
2115
|
+
/**
|
|
2116
|
+
* Get the currently active session in the shape callers can persist and later
|
|
2117
|
+
* pass back to {@link restoreSession}.
|
|
2118
|
+
*/
|
|
2119
|
+
get restorableSession() {
|
|
2120
|
+
return this.currentTinyCloudSession();
|
|
2121
|
+
}
|
|
2050
2122
|
/**
|
|
2051
2123
|
* Sign in and create a new session.
|
|
2052
2124
|
* This creates the user's space if it doesn't exist.
|
|
@@ -2069,8 +2141,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2069
2141
|
this._hooks = void 0;
|
|
2070
2142
|
this._vault = void 0;
|
|
2071
2143
|
this._encryption = void 0;
|
|
2072
|
-
this._baseSecrets
|
|
2073
|
-
this._secrets
|
|
2144
|
+
this._baseSecrets.clear();
|
|
2145
|
+
this._secrets.clear();
|
|
2074
2146
|
this._spaceService = void 0;
|
|
2075
2147
|
this._serviceContext = void 0;
|
|
2076
2148
|
this.runtimePermissionGrants = [];
|
|
@@ -2094,17 +2166,38 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2094
2166
|
return this.wasmBindings.makeSpaceId(this._address, this._chainId, name);
|
|
2095
2167
|
}
|
|
2096
2168
|
async bootstrapAccountIfNeeded() {
|
|
2169
|
+
this._bootstrapSkipped = false;
|
|
2170
|
+
this._bootstrapStatus = { skipped: false };
|
|
2097
2171
|
if (this.config.autoBootstrapAccount === false) {
|
|
2098
2172
|
return false;
|
|
2099
2173
|
}
|
|
2100
2174
|
if (!this.auth || !this._address) {
|
|
2101
2175
|
return false;
|
|
2102
2176
|
}
|
|
2177
|
+
if (isInteractiveSigner(this.config)) {
|
|
2178
|
+
console.debug(
|
|
2179
|
+
"[TinyCloudNode] bootstrap skipped: interactive signer detected. Server-side bootstrap (OpenKey) is expected to have provisioned the account."
|
|
2180
|
+
);
|
|
2181
|
+
this._bootstrapSkipped = true;
|
|
2182
|
+
this._bootstrapStatus = { skipped: true, reason: "interactive-signer" };
|
|
2183
|
+
return false;
|
|
2184
|
+
}
|
|
2103
2185
|
const steps = (0, import_sdk_core8.bootstrapSteps)(this._address, this._chainId);
|
|
2104
2186
|
if (!await this.isFreshBootstrapAccount(steps)) {
|
|
2105
2187
|
return false;
|
|
2106
2188
|
}
|
|
2107
|
-
|
|
2189
|
+
try {
|
|
2190
|
+
await this.runAccountBootstrap(steps);
|
|
2191
|
+
} catch (err) {
|
|
2192
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
2193
|
+
this._bootstrapSkipped = true;
|
|
2194
|
+
this._bootstrapStatus = { skipped: true, reason };
|
|
2195
|
+
this.notificationHandler.warning(
|
|
2196
|
+
`Account bootstrap did not complete: ${reason}`
|
|
2197
|
+
);
|
|
2198
|
+
console.warn(`[TinyCloudNode] account bootstrap failed: ${reason}`);
|
|
2199
|
+
return false;
|
|
2200
|
+
}
|
|
2108
2201
|
return true;
|
|
2109
2202
|
}
|
|
2110
2203
|
async isFreshBootstrapAccount(steps) {
|
|
@@ -2156,16 +2249,23 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2156
2249
|
if (rawAbilities) {
|
|
2157
2250
|
rawAbilitiesBySpace.set(step.space, rawAbilities);
|
|
2158
2251
|
}
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2252
|
+
let session;
|
|
2253
|
+
try {
|
|
2254
|
+
session = await auth.createBootstrapSession({
|
|
2255
|
+
spaceId: step.spaceId,
|
|
2256
|
+
capabilityRequest: step.request ?? import_sdk_core8.BOOTSTRAP_SESSION_REQUESTS[step.space],
|
|
2257
|
+
rawAbilities
|
|
2258
|
+
});
|
|
2259
|
+
} catch (err) {
|
|
2260
|
+
throw new Error(
|
|
2261
|
+
`Account bootstrap aborted: signature rejected for space "${step.space}". Cause: ${err instanceof Error ? err.message : String(err)}`
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2164
2264
|
sessions.set(step.space, session);
|
|
2165
2265
|
}
|
|
2166
2266
|
for (const step of steps) {
|
|
2167
2267
|
if (step.kind !== "host") continue;
|
|
2168
|
-
const hosted = await auth.hostOwnedSpace(step.spaceId);
|
|
2268
|
+
const hosted = await auth.hostOwnedSpace(step.spaceId, "bootstrap-host");
|
|
2169
2269
|
if (!hosted) {
|
|
2170
2270
|
throw new Error(`Failed to host bootstrap space: ${step.spaceId}`);
|
|
2171
2271
|
}
|
|
@@ -2556,8 +2656,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2556
2656
|
this._hooks = void 0;
|
|
2557
2657
|
this._vault = void 0;
|
|
2558
2658
|
this._encryption = void 0;
|
|
2559
|
-
this._baseSecrets
|
|
2560
|
-
this._secrets
|
|
2659
|
+
this._baseSecrets.clear();
|
|
2660
|
+
this._secrets.clear();
|
|
2561
2661
|
this._spaceService = void 0;
|
|
2562
2662
|
this._serviceContext = void 0;
|
|
2563
2663
|
this.runtimePermissionGrants = [];
|
|
@@ -2847,6 +2947,20 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2847
2947
|
getDefaultEncryptionNetworkId(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
2848
2948
|
return `urn:tinycloud:encryption:${this.did}:${name}`;
|
|
2849
2949
|
}
|
|
2950
|
+
getEncryptionNetworkIdForSpace(spaceId, name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
2951
|
+
const ownerDid = this.ownerDidFromSpaceId(spaceId) ?? this.did;
|
|
2952
|
+
return `urn:tinycloud:encryption:${ownerDid}:${name}`;
|
|
2953
|
+
}
|
|
2954
|
+
ownerDidFromSpaceId(spaceId) {
|
|
2955
|
+
if (!spaceId.startsWith("tinycloud:")) return void 0;
|
|
2956
|
+
const body = spaceId.slice("tinycloud:".length);
|
|
2957
|
+
const lastSeparator = body.lastIndexOf(":");
|
|
2958
|
+
if (lastSeparator <= 0) return void 0;
|
|
2959
|
+
const owner = body.slice(0, lastSeparator);
|
|
2960
|
+
if (owner.startsWith("did:")) return owner;
|
|
2961
|
+
if (!owner.includes(":")) return void 0;
|
|
2962
|
+
return `did:${owner}`;
|
|
2963
|
+
}
|
|
2850
2964
|
requireServiceSession() {
|
|
2851
2965
|
const session = this._serviceContext?.session;
|
|
2852
2966
|
if (!session) {
|
|
@@ -3034,7 +3148,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3034
3148
|
spaceId,
|
|
3035
3149
|
crypto: vaultCrypto,
|
|
3036
3150
|
encryption: {
|
|
3037
|
-
networkId: this.
|
|
3151
|
+
networkId: this.getEncryptionNetworkIdForSpace(spaceId),
|
|
3038
3152
|
service: this.getEncryptionService(),
|
|
3039
3153
|
decryptCapabilityProof: () => ({
|
|
3040
3154
|
proofs: [this.requireServiceSession().delegationCid]
|
|
@@ -3165,6 +3279,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3165
3279
|
}
|
|
3166
3280
|
return vaultService;
|
|
3167
3281
|
},
|
|
3282
|
+
createSecretsService: (spaceId) => {
|
|
3283
|
+
return this.secretsForSpace(spaceId);
|
|
3284
|
+
},
|
|
3168
3285
|
// Enable space.delegations.create() via SIWE-based delegation
|
|
3169
3286
|
createDelegation: async (params) => {
|
|
3170
3287
|
try {
|
|
@@ -3287,11 +3404,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3287
3404
|
try {
|
|
3288
3405
|
const host = this.config.host;
|
|
3289
3406
|
const now = /* @__PURE__ */ new Date();
|
|
3290
|
-
const abilities =
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
};
|
|
3407
|
+
const abilities = sharingActionsToAbilities(params.path, params.actions);
|
|
3408
|
+
if (!abilities) {
|
|
3409
|
+
return void 0;
|
|
3410
|
+
}
|
|
3295
3411
|
const prepared = this.wasmBindings.prepareSession({
|
|
3296
3412
|
abilities,
|
|
3297
3413
|
address: this.wasmBindings.ensureEip55(session.address),
|
|
@@ -3547,27 +3663,49 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3547
3663
|
if (!this._spaceService) {
|
|
3548
3664
|
throw new Error("Not signed in. Call signIn() first.");
|
|
3549
3665
|
}
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3666
|
+
return this.secretsForSpace("secrets");
|
|
3667
|
+
}
|
|
3668
|
+
/**
|
|
3669
|
+
* App-facing secrets API backed by the requested space's vault.
|
|
3670
|
+
*/
|
|
3671
|
+
secretsForSpace(spaceId) {
|
|
3672
|
+
if (!this._spaceService) {
|
|
3673
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
3674
|
+
}
|
|
3675
|
+
const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
|
|
3676
|
+
let secrets = this._secrets.get(resolvedSpace);
|
|
3677
|
+
if (!secrets) {
|
|
3678
|
+
secrets = new NodeSecretsService({
|
|
3679
|
+
getService: () => this.getBaseSecrets(resolvedSpace),
|
|
3680
|
+
space: resolvedSpace,
|
|
3553
3681
|
getManifest: () => this.manifest,
|
|
3554
3682
|
hasPermissions: (permissions) => this.hasRuntimePermissions(permissions),
|
|
3555
3683
|
grantPermissions: (additional) => this.grantRuntimePermissions(additional),
|
|
3556
3684
|
canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
|
|
3557
|
-
getEncryptionNetworkId: () => this.
|
|
3685
|
+
getEncryptionNetworkId: () => this.getEncryptionNetworkIdForSpace(resolvedSpace),
|
|
3686
|
+
resolveSpace: (space) => space.startsWith("tinycloud:") ? space : this.ownedSpaceId(space),
|
|
3558
3687
|
getUnlockSigner: () => this.signer ?? void 0
|
|
3559
3688
|
});
|
|
3689
|
+
this._secrets.set(resolvedSpace, secrets);
|
|
3560
3690
|
}
|
|
3561
|
-
return
|
|
3691
|
+
return secrets;
|
|
3562
3692
|
}
|
|
3563
|
-
getBaseSecrets() {
|
|
3693
|
+
getBaseSecrets(spaceId) {
|
|
3564
3694
|
if (!this._spaceService) {
|
|
3565
3695
|
throw new Error("Not signed in. Call signIn() first.");
|
|
3566
3696
|
}
|
|
3567
|
-
|
|
3568
|
-
|
|
3697
|
+
const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
|
|
3698
|
+
let secrets = this._baseSecrets.get(resolvedSpace);
|
|
3699
|
+
if (!secrets) {
|
|
3700
|
+
const kvService = this.createSpaceScopedKVService(resolvedSpace);
|
|
3701
|
+
const vaultService = this.createVaultService(resolvedSpace, kvService);
|
|
3702
|
+
if (this._serviceContext) {
|
|
3703
|
+
vaultService.initialize(this._serviceContext);
|
|
3704
|
+
}
|
|
3705
|
+
secrets = new import_sdk_core8.SecretsService(() => vaultService);
|
|
3706
|
+
this._baseSecrets.set(resolvedSpace, secrets);
|
|
3569
3707
|
}
|
|
3570
|
-
return
|
|
3708
|
+
return secrets;
|
|
3571
3709
|
}
|
|
3572
3710
|
/**
|
|
3573
3711
|
* Hooks write stream subscription API.
|