@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.d.cts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { ACCOUNT_REGISTRY_PATH, ACCOUNT_REGISTRY_SPACE, AccountApplication, AccountApplicationListOptions, AccountDelegation, AccountDelegationListOptions, AccountDelegationRevokeOptions, AccountIndexEnsureResult, AccountIndexRebuildResult, AccountIndexStatus, AccountIndexedReadOptions, AccountService, AccountServiceConfig, AccountSpace, AccountSpaceListOptions, AccountStatus, AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CanonicalAddress, CanonicalParsedNetworkId, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, ClientSession, ColumnInfo, ComposeManifestOptions, ComposedManifestRequest, CreateDelegationParams, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DataVaultConfig, DataVaultService, DatabaseHandle, Delegation, DelegationChain, DelegationChainV2, DelegationDirection, DelegationError, DelegationErrorCode, DelegationErrorCodes, DelegationFilters, DelegationManager, DelegationManagerConfig, DelegationRecord, DelegationResult, DidCacheKeyOptions, DidEqualsOptions, DuckDbAction, DuckDbActionType, DuckDbBatchOptions, DuckDbBatchResponse, DuckDbDatabaseHandle, DuckDbExecuteOptions, DuckDbExecuteResponse, DuckDbOptions, DuckDbQueryOptions, DuckDbQueryResponse, DuckDbService, DuckDbServiceConfig, DuckDbStatement, DuckDbValue, EncodedShareData, ExecuteOptions, ExecuteResponse, Extension, FetchFunction, GenerateShareParams, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, IKVService, INotificationHandler, IPrefixedKVService, ISQLService, ISecretsService, ISessionManager, ISessionStorage, ISharingService, ISigner, ISpace, ISpaceCreationHandler, ISpaceScopedDelegations, ISpaceScopedSharing, ISpaceService, IUserAuthorization, IWasmBindings, IdentityParseError, IngestOptions, InvokeFunction, JWK, KVCreateSignedReadUrlOptions, KVResponse, KVService, KVServiceConfig, KVSignedReadUrlResponse, KeyInfo, KeyProvider, KeyType, Manifest, ManifestDefaults, ManifestRegistryRecord, ManifestSecretActions, ManifestValidationError, OpenKeyCallbackStrategy, OpenKeySigningRequestBody, OpenKeySigningResponseBody, OpenKeySigningStrategyOptions, PermissionEntry, PermissionNotInManifestError, PersistedSessionData, PkhDidParts, PrefixedKVService, ProtocolMismatchError, QueryOptions, QueryResponse, ReceiveOptions, ResolvedCapabilities, ResolvedDelegate, ResolvedSecretPath, ResourceCapability, SECRET_NAME_RE, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SchemaInfo, SecretPayload, SecretScopeOptions, SecretsError, SecretsService, ServiceContext, ServiceContextConfig, ServiceSession, SessionExpiredError, ShareAccess, ShareLink, ShareLinkData, ShareSchema, SharingService, SharingServiceConfig, SignCallback, SignInOptions, SignRequest, SignResponse, SilentNotificationHandler, Space, SpaceAbilitiesMap, SpaceConfig, SpaceCreationContext, SpaceErrorCode, SpaceErrorCodes, SpaceInfo, SpaceOwnership, SpaceService, SpaceServiceConfig, SqlStatement, SqlValue, StoredDelegationChain, TableInfo, TelemetryConfig, TelemetryEventHandler, TinyCloud, TinyCloudConfig, TinyCloudDebugEnableOptions, TinyCloudDebugEvent, TinyCloudDebugLevel, TinyCloudDebugLogger, TinyCloudDebugTimer, TinyCloudSession, UnsupportedFeatureError, VAULT_PERMISSION_SERVICE, VaultCrypto, VaultEntry, VaultError, VaultGetOptions, VaultGrantOptions, VaultHeaders, VaultListOptions, VaultPublicSpaceKVActions, VaultPutOptions, VersionCheckError, ViewInfo, WasmVaultFunctions, addressStorageKey, buildSpaceUri, canonicalizeAddress, canonicalizeDid, canonicalizeDidUrl, canonicalizeNetworkId, canonicalizeSecretScope, checkNodeInfo, clearTinyCloudDebugLogs, composeManifestRequest, createCapabilityKeyRegistry, createOpenKeyCallbackSigningStrategy, createSharingService, createSpaceService, createVaultCrypto, defaultSpaceCreationHandler, didCacheKey, didEquals, disableTinyCloudDebug, enableTinyCloudDebug, expandActionShortNames, expandPermissionEntries, expandPermissionEntry, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, isCapabilitySubset, isEvmAddress, loadManifest, makePkhSpaceId, makePublicSpaceId, parseCanonicalNetworkId, parseExpiry, parsePkhDid, parseSpaceUri, pkhDid, principalDid, principalDidEquals, resolveManifest, resolveSecretListPrefix, resolveSecretPath, resourceCapabilitiesToSpaceAbilitiesMap, tinyCloudDebugLogger, validateManifest } from '@tinycloud/sdk-core';
2
- export { D as DelegateToOptions, b as DelegateToResult, c as DelegatedAccess, F as FileSessionStorage, M as MemorySessionStorage, N as NodeEventEmitterStrategy, e as NodeUserAuthorization, f as NodeUserAuthorizationConfig, P as PortableDelegation, g as RuntimePermissionGrantOptions, S as SignStrategy, T as TinyCloudNode, h as TinyCloudNodeConfig, W as WasmKeyProvider, i as WasmKeyProviderConfig, j as createWasmKeyProvider, k as defaultSignStrategy, l as deserializeDelegation, s as serializeDelegation } from './core-DfE4s_Rg.cjs';
2
+ export { D as DelegateToOptions, b as DelegateToResult, c as DelegatedAccess, F as FileSessionStorage, M as MemorySessionStorage, N as NodeEventEmitterStrategy, e as NodeUserAuthorization, f as NodeUserAuthorizationConfig, P as PortableDelegation, g as RuntimePermissionGrantOptions, S as SignStrategy, T as TinyCloudNode, h as TinyCloudNodeConfig, W as WasmKeyProvider, i as WasmKeyProviderConfig, j as createWasmKeyProvider, k as defaultSignStrategy, l as deserializeDelegation, s as serializeDelegation } from './core-ojeY-wet.cjs';
3
3
  import 'events';
4
4
  import '@tinycloud/sdk-services';
package/dist/core.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { ACCOUNT_REGISTRY_PATH, ACCOUNT_REGISTRY_SPACE, AccountApplication, AccountApplicationListOptions, AccountDelegation, AccountDelegationListOptions, AccountDelegationRevokeOptions, AccountIndexEnsureResult, AccountIndexRebuildResult, AccountIndexStatus, AccountIndexedReadOptions, AccountService, AccountServiceConfig, AccountSpace, AccountSpaceListOptions, AccountStatus, AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CanonicalAddress, CanonicalParsedNetworkId, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, ClientSession, ColumnInfo, ComposeManifestOptions, ComposedManifestRequest, CreateDelegationParams, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DataVaultConfig, DataVaultService, DatabaseHandle, Delegation, DelegationChain, DelegationChainV2, DelegationDirection, DelegationError, DelegationErrorCode, DelegationErrorCodes, DelegationFilters, DelegationManager, DelegationManagerConfig, DelegationRecord, DelegationResult, DidCacheKeyOptions, DidEqualsOptions, DuckDbAction, DuckDbActionType, DuckDbBatchOptions, DuckDbBatchResponse, DuckDbDatabaseHandle, DuckDbExecuteOptions, DuckDbExecuteResponse, DuckDbOptions, DuckDbQueryOptions, DuckDbQueryResponse, DuckDbService, DuckDbServiceConfig, DuckDbStatement, DuckDbValue, EncodedShareData, ExecuteOptions, ExecuteResponse, Extension, FetchFunction, GenerateShareParams, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, IKVService, INotificationHandler, IPrefixedKVService, ISQLService, ISecretsService, ISessionManager, ISessionStorage, ISharingService, ISigner, ISpace, ISpaceCreationHandler, ISpaceScopedDelegations, ISpaceScopedSharing, ISpaceService, IUserAuthorization, IWasmBindings, IdentityParseError, IngestOptions, InvokeFunction, JWK, KVCreateSignedReadUrlOptions, KVResponse, KVService, KVServiceConfig, KVSignedReadUrlResponse, KeyInfo, KeyProvider, KeyType, Manifest, ManifestDefaults, ManifestRegistryRecord, ManifestSecretActions, ManifestValidationError, OpenKeyCallbackStrategy, OpenKeySigningRequestBody, OpenKeySigningResponseBody, OpenKeySigningStrategyOptions, PermissionEntry, PermissionNotInManifestError, PersistedSessionData, PkhDidParts, PrefixedKVService, ProtocolMismatchError, QueryOptions, QueryResponse, ReceiveOptions, ResolvedCapabilities, ResolvedDelegate, ResolvedSecretPath, ResourceCapability, SECRET_NAME_RE, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SchemaInfo, SecretPayload, SecretScopeOptions, SecretsError, SecretsService, ServiceContext, ServiceContextConfig, ServiceSession, SessionExpiredError, ShareAccess, ShareLink, ShareLinkData, ShareSchema, SharingService, SharingServiceConfig, SignCallback, SignInOptions, SignRequest, SignResponse, SilentNotificationHandler, Space, SpaceAbilitiesMap, SpaceConfig, SpaceCreationContext, SpaceErrorCode, SpaceErrorCodes, SpaceInfo, SpaceOwnership, SpaceService, SpaceServiceConfig, SqlStatement, SqlValue, StoredDelegationChain, TableInfo, TelemetryConfig, TelemetryEventHandler, TinyCloud, TinyCloudConfig, TinyCloudDebugEnableOptions, TinyCloudDebugEvent, TinyCloudDebugLevel, TinyCloudDebugLogger, TinyCloudDebugTimer, TinyCloudSession, UnsupportedFeatureError, VAULT_PERMISSION_SERVICE, VaultCrypto, VaultEntry, VaultError, VaultGetOptions, VaultGrantOptions, VaultHeaders, VaultListOptions, VaultPublicSpaceKVActions, VaultPutOptions, VersionCheckError, ViewInfo, WasmVaultFunctions, addressStorageKey, buildSpaceUri, canonicalizeAddress, canonicalizeDid, canonicalizeDidUrl, canonicalizeNetworkId, canonicalizeSecretScope, checkNodeInfo, clearTinyCloudDebugLogs, composeManifestRequest, createCapabilityKeyRegistry, createOpenKeyCallbackSigningStrategy, createSharingService, createSpaceService, createVaultCrypto, defaultSpaceCreationHandler, didCacheKey, didEquals, disableTinyCloudDebug, enableTinyCloudDebug, expandActionShortNames, expandPermissionEntries, expandPermissionEntry, getTinyCloudDebugLogs, installTinyCloudDebugGlobals, isCapabilitySubset, isEvmAddress, loadManifest, makePkhSpaceId, makePublicSpaceId, parseCanonicalNetworkId, parseExpiry, parsePkhDid, parseSpaceUri, pkhDid, principalDid, principalDidEquals, resolveManifest, resolveSecretListPrefix, resolveSecretPath, resourceCapabilitiesToSpaceAbilitiesMap, tinyCloudDebugLogger, validateManifest } from '@tinycloud/sdk-core';
2
- export { D as DelegateToOptions, b as DelegateToResult, c as DelegatedAccess, F as FileSessionStorage, M as MemorySessionStorage, N as NodeEventEmitterStrategy, e as NodeUserAuthorization, f as NodeUserAuthorizationConfig, P as PortableDelegation, g as RuntimePermissionGrantOptions, S as SignStrategy, T as TinyCloudNode, h as TinyCloudNodeConfig, W as WasmKeyProvider, i as WasmKeyProviderConfig, j as createWasmKeyProvider, k as defaultSignStrategy, l as deserializeDelegation, s as serializeDelegation } from './core-DfE4s_Rg.js';
2
+ export { D as DelegateToOptions, b as DelegateToResult, c as DelegatedAccess, F as FileSessionStorage, M as MemorySessionStorage, N as NodeEventEmitterStrategy, e as NodeUserAuthorization, f as NodeUserAuthorizationConfig, P as PortableDelegation, g as RuntimePermissionGrantOptions, S as SignStrategy, T as TinyCloudNode, h as TinyCloudNodeConfig, W as WasmKeyProvider, i as WasmKeyProviderConfig, j as createWasmKeyProvider, k as defaultSignStrategy, l as deserializeDelegation, s as serializeDelegation } from './core-ojeY-wet.js';
3
3
  import 'events';
4
4
  import '@tinycloud/sdk-services';
package/dist/core.js CHANGED
@@ -620,7 +620,7 @@ var NodeUserAuthorization = class {
620
620
  * Create the space on the TinyCloud server (host delegation).
621
621
  * This registers the user as the owner of the space.
622
622
  */
623
- async hostSpace(targetSpaceId) {
623
+ async hostSpace(targetSpaceId, purpose) {
624
624
  if (!this._tinyCloudSession || !this._address || !this._chainId) {
625
625
  throw new Error("Must be signed in to host space");
626
626
  }
@@ -636,7 +636,7 @@ var NodeUserAuthorization = class {
636
636
  spaceId,
637
637
  peerId
638
638
  });
639
- const signature = await this.signMessage(siwe);
639
+ const signature = await this.signMessage(siwe, purpose);
640
640
  const headers = this.wasm.siweToDelegationHeaders({ siwe, signature });
641
641
  const result = await submitHostDelegation(host, headers);
642
642
  return result.success;
@@ -652,8 +652,8 @@ var NodeUserAuthorization = class {
652
652
  * Create a specific owned space on the server via host delegation.
653
653
  * Used by manifest registry setup for the account space.
654
654
  */
655
- async hostOwnedSpace(spaceId) {
656
- return this.hostSpace(spaceId);
655
+ async hostOwnedSpace(spaceId, purpose) {
656
+ return this.hostSpace(spaceId, purpose);
657
657
  }
658
658
  /**
659
659
  * Ensure the user's space exists on the TinyCloud server.
@@ -803,7 +803,8 @@ var NodeUserAuthorization = class {
803
803
  address,
804
804
  chainId,
805
805
  message: prepared.siwe,
806
- type: "siwe"
806
+ type: "siwe",
807
+ purpose: "bootstrap-session"
807
808
  });
808
809
  const session = this.wasm.completeSessionSetup({
809
810
  ...prepared,
@@ -867,7 +868,8 @@ var NodeUserAuthorization = class {
867
868
  address,
868
869
  chainId,
869
870
  message: prepared.siwe,
870
- type: "siwe"
871
+ type: "siwe",
872
+ purpose: "sign-in"
871
873
  });
872
874
  const session = this.wasm.completeSessionSetup({
873
875
  ...prepared,
@@ -955,7 +957,7 @@ var NodeUserAuthorization = class {
955
957
  /**
956
958
  * Sign a message with the connected signer.
957
959
  */
958
- async signMessage(message) {
960
+ async signMessage(message, purpose) {
959
961
  if (!this._address) {
960
962
  this._address = canonicalizeAddress(await this.signer.getAddress());
961
963
  }
@@ -966,7 +968,8 @@ var NodeUserAuthorization = class {
966
968
  address: this._address,
967
969
  chainId: this._chainId,
968
970
  message,
969
- type: "message"
971
+ type: "message",
972
+ ...purpose ? { purpose } : {}
970
973
  });
971
974
  }
972
975
  /**
@@ -1498,12 +1501,12 @@ function displayActionUrn(action) {
1498
1501
  function secretActionName(action) {
1499
1502
  return action;
1500
1503
  }
1501
- function secretPermissionEntries(name, options, action, encryptionNetworkId) {
1504
+ function secretPermissionEntries(name, options, action, space, encryptionNetworkId) {
1502
1505
  const entries = [];
1503
1506
  const path = action === "list" ? resolveSecretListPrefix(options) : resolveSecretPath(name, options).permissionPaths.vault;
1504
1507
  entries.push({
1505
1508
  service: "tinycloud.kv",
1506
- space: SECRETS_SPACE,
1509
+ space,
1507
1510
  path,
1508
1511
  actions: [secretActionName(action)],
1509
1512
  skipPrefix: true
@@ -1518,11 +1521,23 @@ function secretPermissionEntries(name, options, action, encryptionNetworkId) {
1518
1521
  }
1519
1522
  return entries;
1520
1523
  }
1524
+ function normalizeSpace(space, resolveSpace) {
1525
+ if (!space) return void 0;
1526
+ if (space.startsWith("tinycloud:")) return space;
1527
+ return resolveSpace?.(space) ?? space;
1528
+ }
1529
+ function spaceMatches(granted, requested, resolveSpace) {
1530
+ if (!granted || !requested) return false;
1531
+ return normalizeSpace(granted, resolveSpace) === normalizeSpace(requested, resolveSpace);
1532
+ }
1521
1533
  var NodeSecretsService = class {
1522
1534
  constructor(config) {
1523
1535
  this.config = config;
1524
1536
  this.shouldRestoreUnlock = false;
1525
1537
  }
1538
+ get space() {
1539
+ return this.config.space ?? SECRETS_SPACE;
1540
+ }
1526
1541
  get vault() {
1527
1542
  return this.service.vault;
1528
1543
  }
@@ -1575,6 +1590,7 @@ var NodeSecretsService = class {
1575
1590
  name,
1576
1591
  options,
1577
1592
  action,
1593
+ this.space,
1578
1594
  action === "get" ? this.config.getEncryptionNetworkId?.() : void 0
1579
1595
  );
1580
1596
  } catch (error) {
@@ -1624,7 +1640,7 @@ var NodeSecretsService = class {
1624
1640
  (entry) => manifests.some((candidate) => {
1625
1641
  const resolved = resolveManifest(candidate);
1626
1642
  return resolved.resources.some(
1627
- (resource) => resource.service === entry.service && resource.space === entry.space && resource.path === entry.path && entry.actions.every((action) => resource.actions.includes(action))
1643
+ (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))
1628
1644
  );
1629
1645
  })
1630
1646
  );
@@ -1641,6 +1657,15 @@ var DEFAULT_SESSION_EXPIRATION_MS = EXPIRY3.SESSION_MS;
1641
1657
  function isOpenKeyAutoSignStrategy(strategy) {
1642
1658
  return strategy?.openKeyAutoSign === true;
1643
1659
  }
1660
+ function isInteractiveSigner(config) {
1661
+ if (config.privateKey) {
1662
+ return false;
1663
+ }
1664
+ if (isOpenKeyAutoSignStrategy(config.signStrategy)) {
1665
+ return false;
1666
+ }
1667
+ return config.signer !== void 0;
1668
+ }
1644
1669
  function didPrincipalMatches2(actual, expected) {
1645
1670
  try {
1646
1671
  return principalDidEquals2(actual, expected);
@@ -1648,6 +1673,20 @@ function didPrincipalMatches2(actual, expected) {
1648
1673
  return actual === expected;
1649
1674
  }
1650
1675
  }
1676
+ function sharingActionsToAbilities(path, actions) {
1677
+ var _a;
1678
+ const abilities = {};
1679
+ for (const action of actions) {
1680
+ const slash = action.indexOf("/");
1681
+ if (slash === -1) return void 0;
1682
+ const shortService = SERVICE_LONG_TO_SHORT[action.slice(0, slash)];
1683
+ if (shortService === void 0) return void 0;
1684
+ abilities[shortService] ?? (abilities[shortService] = {});
1685
+ (_a = abilities[shortService])[path] ?? (_a[path] = []);
1686
+ abilities[shortService][path].push(action);
1687
+ }
1688
+ return Object.keys(abilities).length > 0 ? abilities : void 0;
1689
+ }
1651
1690
  function base64UrlEncode(bytes) {
1652
1691
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
1653
1692
  let output = "";
@@ -1760,7 +1799,24 @@ var _TinyCloudNode = class _TinyCloudNode {
1760
1799
  this.auth = null;
1761
1800
  this.tc = null;
1762
1801
  this._chainId = 1;
1802
+ this._baseSecrets = /* @__PURE__ */ new Map();
1803
+ this._secrets = /* @__PURE__ */ new Map();
1763
1804
  this.runtimePermissionGrants = [];
1805
+ /**
1806
+ * True when the last signIn() detected an interactive signer and skipped
1807
+ * client-side bootstrap. Apps can read this to know whether bootstrap was
1808
+ * deferred to the server (OpenKey) or requires a separate user action.
1809
+ */
1810
+ this._bootstrapSkipped = false;
1811
+ /**
1812
+ * Outcome of the last signIn()'s account-bootstrap attempt. `skipped` is
1813
+ * true when bootstrap did not complete (interactive signer, auto-sign
1814
+ * denied, or a bootstrap step failed); `reason` carries the cause so apps
1815
+ * can surface a "finish account setup" call-to-action.
1816
+ */
1817
+ this._bootstrapStatus = {
1818
+ skipped: false
1819
+ };
1764
1820
  this.invokeWithRuntimePermissions = (session, service, path, action, facts) => {
1765
1821
  return this.wasmBindings.invoke(
1766
1822
  this.selectInvocationSession(session, service, path, action),
@@ -1853,6 +1909,15 @@ var _TinyCloudNode = class _TinyCloudNode {
1853
1909
  static registerNodeDefaults(defaults) {
1854
1910
  _TinyCloudNode.nodeDefaults = defaults;
1855
1911
  }
1912
+ /** Whether the last signIn() skipped client-side bootstrap because the
1913
+ * signer is interactive (browser wallet / EIP-1193 provider). */
1914
+ get bootstrapSkipped() {
1915
+ return this._bootstrapSkipped;
1916
+ }
1917
+ /** Outcome of the last signIn()'s account-bootstrap attempt. */
1918
+ get bootstrapStatus() {
1919
+ return this._bootstrapStatus;
1920
+ }
1856
1921
  get nodeFeatures() {
1857
1922
  return this.auth?.nodeFeatures ?? [];
1858
1923
  }
@@ -2022,6 +2087,13 @@ var _TinyCloudNode = class _TinyCloudNode {
2022
2087
  get session() {
2023
2088
  return this.auth?.tinyCloudSession;
2024
2089
  }
2090
+ /**
2091
+ * Get the currently active session in the shape callers can persist and later
2092
+ * pass back to {@link restoreSession}.
2093
+ */
2094
+ get restorableSession() {
2095
+ return this.currentTinyCloudSession();
2096
+ }
2025
2097
  /**
2026
2098
  * Sign in and create a new session.
2027
2099
  * This creates the user's space if it doesn't exist.
@@ -2044,8 +2116,8 @@ var _TinyCloudNode = class _TinyCloudNode {
2044
2116
  this._hooks = void 0;
2045
2117
  this._vault = void 0;
2046
2118
  this._encryption = void 0;
2047
- this._baseSecrets = void 0;
2048
- this._secrets = void 0;
2119
+ this._baseSecrets.clear();
2120
+ this._secrets.clear();
2049
2121
  this._spaceService = void 0;
2050
2122
  this._serviceContext = void 0;
2051
2123
  this.runtimePermissionGrants = [];
@@ -2069,17 +2141,38 @@ var _TinyCloudNode = class _TinyCloudNode {
2069
2141
  return this.wasmBindings.makeSpaceId(this._address, this._chainId, name);
2070
2142
  }
2071
2143
  async bootstrapAccountIfNeeded() {
2144
+ this._bootstrapSkipped = false;
2145
+ this._bootstrapStatus = { skipped: false };
2072
2146
  if (this.config.autoBootstrapAccount === false) {
2073
2147
  return false;
2074
2148
  }
2075
2149
  if (!this.auth || !this._address) {
2076
2150
  return false;
2077
2151
  }
2152
+ if (isInteractiveSigner(this.config)) {
2153
+ console.debug(
2154
+ "[TinyCloudNode] bootstrap skipped: interactive signer detected. Server-side bootstrap (OpenKey) is expected to have provisioned the account."
2155
+ );
2156
+ this._bootstrapSkipped = true;
2157
+ this._bootstrapStatus = { skipped: true, reason: "interactive-signer" };
2158
+ return false;
2159
+ }
2078
2160
  const steps = bootstrapSteps(this._address, this._chainId);
2079
2161
  if (!await this.isFreshBootstrapAccount(steps)) {
2080
2162
  return false;
2081
2163
  }
2082
- await this.runAccountBootstrap(steps);
2164
+ try {
2165
+ await this.runAccountBootstrap(steps);
2166
+ } catch (err) {
2167
+ const reason = err instanceof Error ? err.message : String(err);
2168
+ this._bootstrapSkipped = true;
2169
+ this._bootstrapStatus = { skipped: true, reason };
2170
+ this.notificationHandler.warning(
2171
+ `Account bootstrap did not complete: ${reason}`
2172
+ );
2173
+ console.warn(`[TinyCloudNode] account bootstrap failed: ${reason}`);
2174
+ return false;
2175
+ }
2083
2176
  return true;
2084
2177
  }
2085
2178
  async isFreshBootstrapAccount(steps) {
@@ -2131,16 +2224,23 @@ var _TinyCloudNode = class _TinyCloudNode {
2131
2224
  if (rawAbilities) {
2132
2225
  rawAbilitiesBySpace.set(step.space, rawAbilities);
2133
2226
  }
2134
- const session = await auth.createBootstrapSession({
2135
- spaceId: step.spaceId,
2136
- capabilityRequest: step.request ?? BOOTSTRAP_SESSION_REQUESTS[step.space],
2137
- rawAbilities
2138
- });
2227
+ let session;
2228
+ try {
2229
+ session = await auth.createBootstrapSession({
2230
+ spaceId: step.spaceId,
2231
+ capabilityRequest: step.request ?? BOOTSTRAP_SESSION_REQUESTS[step.space],
2232
+ rawAbilities
2233
+ });
2234
+ } catch (err) {
2235
+ throw new Error(
2236
+ `Account bootstrap aborted: signature rejected for space "${step.space}". Cause: ${err instanceof Error ? err.message : String(err)}`
2237
+ );
2238
+ }
2139
2239
  sessions.set(step.space, session);
2140
2240
  }
2141
2241
  for (const step of steps) {
2142
2242
  if (step.kind !== "host") continue;
2143
- const hosted = await auth.hostOwnedSpace(step.spaceId);
2243
+ const hosted = await auth.hostOwnedSpace(step.spaceId, "bootstrap-host");
2144
2244
  if (!hosted) {
2145
2245
  throw new Error(`Failed to host bootstrap space: ${step.spaceId}`);
2146
2246
  }
@@ -2531,8 +2631,8 @@ var _TinyCloudNode = class _TinyCloudNode {
2531
2631
  this._hooks = void 0;
2532
2632
  this._vault = void 0;
2533
2633
  this._encryption = void 0;
2534
- this._baseSecrets = void 0;
2535
- this._secrets = void 0;
2634
+ this._baseSecrets.clear();
2635
+ this._secrets.clear();
2536
2636
  this._spaceService = void 0;
2537
2637
  this._serviceContext = void 0;
2538
2638
  this.runtimePermissionGrants = [];
@@ -2822,6 +2922,20 @@ var _TinyCloudNode = class _TinyCloudNode {
2822
2922
  getDefaultEncryptionNetworkId(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
2823
2923
  return `urn:tinycloud:encryption:${this.did}:${name}`;
2824
2924
  }
2925
+ getEncryptionNetworkIdForSpace(spaceId, name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
2926
+ const ownerDid = this.ownerDidFromSpaceId(spaceId) ?? this.did;
2927
+ return `urn:tinycloud:encryption:${ownerDid}:${name}`;
2928
+ }
2929
+ ownerDidFromSpaceId(spaceId) {
2930
+ if (!spaceId.startsWith("tinycloud:")) return void 0;
2931
+ const body = spaceId.slice("tinycloud:".length);
2932
+ const lastSeparator = body.lastIndexOf(":");
2933
+ if (lastSeparator <= 0) return void 0;
2934
+ const owner = body.slice(0, lastSeparator);
2935
+ if (owner.startsWith("did:")) return owner;
2936
+ if (!owner.includes(":")) return void 0;
2937
+ return `did:${owner}`;
2938
+ }
2825
2939
  requireServiceSession() {
2826
2940
  const session = this._serviceContext?.session;
2827
2941
  if (!session) {
@@ -3009,7 +3123,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3009
3123
  spaceId,
3010
3124
  crypto: vaultCrypto,
3011
3125
  encryption: {
3012
- networkId: this.getDefaultEncryptionNetworkId(),
3126
+ networkId: this.getEncryptionNetworkIdForSpace(spaceId),
3013
3127
  service: this.getEncryptionService(),
3014
3128
  decryptCapabilityProof: () => ({
3015
3129
  proofs: [this.requireServiceSession().delegationCid]
@@ -3140,6 +3254,9 @@ var _TinyCloudNode = class _TinyCloudNode {
3140
3254
  }
3141
3255
  return vaultService;
3142
3256
  },
3257
+ createSecretsService: (spaceId) => {
3258
+ return this.secretsForSpace(spaceId);
3259
+ },
3143
3260
  // Enable space.delegations.create() via SIWE-based delegation
3144
3261
  createDelegation: async (params) => {
3145
3262
  try {
@@ -3262,11 +3379,10 @@ var _TinyCloudNode = class _TinyCloudNode {
3262
3379
  try {
3263
3380
  const host = this.config.host;
3264
3381
  const now = /* @__PURE__ */ new Date();
3265
- const abilities = {
3266
- kv: {
3267
- [params.path]: params.actions
3268
- }
3269
- };
3382
+ const abilities = sharingActionsToAbilities(params.path, params.actions);
3383
+ if (!abilities) {
3384
+ return void 0;
3385
+ }
3270
3386
  const prepared = this.wasmBindings.prepareSession({
3271
3387
  abilities,
3272
3388
  address: this.wasmBindings.ensureEip55(session.address),
@@ -3522,27 +3638,49 @@ var _TinyCloudNode = class _TinyCloudNode {
3522
3638
  if (!this._spaceService) {
3523
3639
  throw new Error("Not signed in. Call signIn() first.");
3524
3640
  }
3525
- if (!this._secrets) {
3526
- this._secrets = new NodeSecretsService({
3527
- getService: () => this.getBaseSecrets(),
3641
+ return this.secretsForSpace("secrets");
3642
+ }
3643
+ /**
3644
+ * App-facing secrets API backed by the requested space's vault.
3645
+ */
3646
+ secretsForSpace(spaceId) {
3647
+ if (!this._spaceService) {
3648
+ throw new Error("Not signed in. Call signIn() first.");
3649
+ }
3650
+ const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
3651
+ let secrets = this._secrets.get(resolvedSpace);
3652
+ if (!secrets) {
3653
+ secrets = new NodeSecretsService({
3654
+ getService: () => this.getBaseSecrets(resolvedSpace),
3655
+ space: resolvedSpace,
3528
3656
  getManifest: () => this.manifest,
3529
3657
  hasPermissions: (permissions) => this.hasRuntimePermissions(permissions),
3530
3658
  grantPermissions: (additional) => this.grantRuntimePermissions(additional),
3531
3659
  canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
3532
- getEncryptionNetworkId: () => this.getDefaultEncryptionNetworkId(),
3660
+ getEncryptionNetworkId: () => this.getEncryptionNetworkIdForSpace(resolvedSpace),
3661
+ resolveSpace: (space) => space.startsWith("tinycloud:") ? space : this.ownedSpaceId(space),
3533
3662
  getUnlockSigner: () => this.signer ?? void 0
3534
3663
  });
3664
+ this._secrets.set(resolvedSpace, secrets);
3535
3665
  }
3536
- return this._secrets;
3666
+ return secrets;
3537
3667
  }
3538
- getBaseSecrets() {
3668
+ getBaseSecrets(spaceId) {
3539
3669
  if (!this._spaceService) {
3540
3670
  throw new Error("Not signed in. Call signIn() first.");
3541
3671
  }
3542
- if (!this._baseSecrets) {
3543
- this._baseSecrets = new SecretsService(() => this.space("secrets").vault);
3672
+ const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
3673
+ let secrets = this._baseSecrets.get(resolvedSpace);
3674
+ if (!secrets) {
3675
+ const kvService = this.createSpaceScopedKVService(resolvedSpace);
3676
+ const vaultService = this.createVaultService(resolvedSpace, kvService);
3677
+ if (this._serviceContext) {
3678
+ vaultService.initialize(this._serviceContext);
3679
+ }
3680
+ secrets = new SecretsService(() => vaultService);
3681
+ this._baseSecrets.set(resolvedSpace, secrets);
3544
3682
  }
3545
- return this._baseSecrets;
3683
+ return secrets;
3546
3684
  }
3547
3685
  /**
3548
3686
  * Hooks write stream subscription API.