@tinycloud/node-sdk 2.11.0-beta.10 → 2.11.0-beta.11

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, AccountApplicationRegisterOptions, AccountDelegation, AccountDelegationListOptions, AccountDelegationRevokeOptions, AccountIndexEnsureResult, AccountIndexRebuildResult, AccountIndexStatus, AccountIndexedReadOptions, AccountService, AccountServiceConfig, AccountSpace, AccountSpaceListOptions, AccountStatus, AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CanonicalAddress, CanonicalParsedNetworkId, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, CaveatedDelegationUnsupportedError, ClientSession, ColumnInfo, ComposeManifestOptions, ComposedManifestRequest, CreateDelegationParams, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DataVaultConfig, DataVaultService, DatabaseHandle, DelegateReceivedShareParams, DelegatedShareAccess, 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, KVBatchReadResponse, KVCreateSignedReadUrlOptions, KVResponse, KVService, KVServiceConfig, KVSignedReadUrlResponse, KeyInfo, KeyProvider, KeyType, Manifest, ManifestDefaults, ManifestRegistryRecord, ManifestSecretActions, ManifestValidationError, OpenKeyCallbackStrategy, OpenKeySigningRequestBody, OpenKeySigningResponseBody, OpenKeySigningStrategyOptions, OwnerSharePolicyRegistrationReceipt, PermissionEntry, PermissionNotInManifestError, PersistedSessionData, PkhDidParts, PrefixedKVService, ProtocolMismatchError, QueryOptions, QueryResponse, ReceiveOptions, RegisterBatchSuccess, RegisterOwnerSharePolicyParams, 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, VaultNetworkReadResult, 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 { B as BootstrapWarning, C as CreateOwnerDelegationParams, D as DelegateToOptions, b as DelegateToResult, c as DelegatedAccess, E as EnsureEncryptionNetworkOptions, F as FileSessionStorage, M as MemorySessionStorage, N as NodeEventEmitterStrategy, e as NodeUserAuthorization, f as NodeUserAuthorizationConfig, O as OwnerDelegationReceipt, P as PortableDelegation, h as RuntimePermissionGrantOptions, S as SecretPermissionHint, i as SecretReadInput, j as SecretReadResult, k as SignStrategy, T as TinyCloudNode, l as TinyCloudNodeConfig, U as UnsupportedSessionRestoreError, W as WasmKeyProvider, m as WasmKeyProviderConfig, o as createWasmKeyProvider, p as defaultSignStrategy, q as deserializeDelegation, s as serializeDelegation } from './core-BypriIWK.cjs';
2
+ export { e as BootstrapWarning, C as CreateOwnerDelegationParams, D as DelegateToOptions, f as DelegateToResult, g as DelegatedAccess, E as EnsureEncryptionNetworkOptions, F as FileSessionStorage, M as MemorySessionStorage, N as NodeEventEmitterStrategy, i as NodeUserAuthorization, j as NodeUserAuthorizationConfig, O as OwnerDelegationReceipt, P as PortableDelegation, l as RuntimePermissionGrantOptions, S as SecretPermissionHint, m as SecretReadInput, n as SecretReadResult, o as SignStrategy, T as TinyCloudNode, p as TinyCloudNodeConfig, U as UnsupportedSessionRestoreError, W as WasmKeyProvider, q as WasmKeyProviderConfig, s as createWasmKeyProvider, t as defaultSignStrategy, u as deserializeDelegation, w as serializeDelegation } from './core-9mWw3N8i.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, AccountApplicationRegisterOptions, AccountDelegation, AccountDelegationListOptions, AccountDelegationRevokeOptions, AccountIndexEnsureResult, AccountIndexRebuildResult, AccountIndexStatus, AccountIndexedReadOptions, AccountService, AccountServiceConfig, AccountSpace, AccountSpaceListOptions, AccountStatus, AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CanonicalAddress, CanonicalParsedNetworkId, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, CaveatedDelegationUnsupportedError, ClientSession, ColumnInfo, ComposeManifestOptions, ComposedManifestRequest, CreateDelegationParams, DEFAULT_MANIFEST_SPACE, DEFAULT_MANIFEST_VERSION, DEFAULT_SIGNED_READ_URL_EXPIRY_MS, DataVaultConfig, DataVaultService, DatabaseHandle, DelegateReceivedShareParams, DelegatedShareAccess, 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, KVBatchReadResponse, KVCreateSignedReadUrlOptions, KVResponse, KVService, KVServiceConfig, KVSignedReadUrlResponse, KeyInfo, KeyProvider, KeyType, Manifest, ManifestDefaults, ManifestRegistryRecord, ManifestSecretActions, ManifestValidationError, OpenKeyCallbackStrategy, OpenKeySigningRequestBody, OpenKeySigningResponseBody, OpenKeySigningStrategyOptions, OwnerSharePolicyRegistrationReceipt, PermissionEntry, PermissionNotInManifestError, PersistedSessionData, PkhDidParts, PrefixedKVService, ProtocolMismatchError, QueryOptions, QueryResponse, ReceiveOptions, RegisterBatchSuccess, RegisterOwnerSharePolicyParams, 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, VaultNetworkReadResult, 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 { B as BootstrapWarning, C as CreateOwnerDelegationParams, D as DelegateToOptions, b as DelegateToResult, c as DelegatedAccess, E as EnsureEncryptionNetworkOptions, F as FileSessionStorage, M as MemorySessionStorage, N as NodeEventEmitterStrategy, e as NodeUserAuthorization, f as NodeUserAuthorizationConfig, O as OwnerDelegationReceipt, P as PortableDelegation, h as RuntimePermissionGrantOptions, S as SecretPermissionHint, i as SecretReadInput, j as SecretReadResult, k as SignStrategy, T as TinyCloudNode, l as TinyCloudNodeConfig, U as UnsupportedSessionRestoreError, W as WasmKeyProvider, m as WasmKeyProviderConfig, o as createWasmKeyProvider, p as defaultSignStrategy, q as deserializeDelegation, s as serializeDelegation } from './core-BypriIWK.js';
2
+ export { e as BootstrapWarning, C as CreateOwnerDelegationParams, D as DelegateToOptions, f as DelegateToResult, g as DelegatedAccess, E as EnsureEncryptionNetworkOptions, F as FileSessionStorage, M as MemorySessionStorage, N as NodeEventEmitterStrategy, i as NodeUserAuthorization, j as NodeUserAuthorizationConfig, O as OwnerDelegationReceipt, P as PortableDelegation, l as RuntimePermissionGrantOptions, S as SecretPermissionHint, m as SecretReadInput, n as SecretReadResult, o as SignStrategy, T as TinyCloudNode, p as TinyCloudNodeConfig, U as UnsupportedSessionRestoreError, W as WasmKeyProvider, q as WasmKeyProviderConfig, s as createWasmKeyProvider, t as defaultSignStrategy, u as deserializeDelegation, w as serializeDelegation } from './core-9mWw3N8i.js';
3
3
  import 'events';
4
4
  import '@tinycloud/sdk-services';
package/dist/core.js CHANGED
@@ -245,6 +245,8 @@ import {
245
245
  extractRecapAttenuations,
246
246
  unauthorizedRecapCapabilities,
247
247
  parseCanonicalRecapResource,
248
+ ACCOUNT_REGISTRY_SPACE,
249
+ ACCOUNT_MANIFEST_PERMISSIONS,
248
250
  KV,
249
251
  SQL,
250
252
  DUCKDB,
@@ -298,6 +300,16 @@ function addRawAbility(rawAbilities, resource, action) {
298
300
  actions.push(action);
299
301
  }
300
302
  }
303
+ function cloneAbilitiesMap(actions) {
304
+ return Object.fromEntries(
305
+ Object.entries(actions).map(([service, paths]) => [
306
+ service,
307
+ Object.fromEntries(
308
+ Object.entries(paths).map(([path, pathActions]) => [path, [...pathActions]])
309
+ )
310
+ ])
311
+ );
312
+ }
301
313
  var NodeUserAuthorization = class {
302
314
  constructor(config) {
303
315
  this.activeSessionKeyId = "default";
@@ -569,23 +581,41 @@ var NodeUserAuthorization = class {
569
581
  const defaultNetworkId = this.defaultEncryptionNetworkId(address, chainId);
570
582
  const primarySpaceId2 = makePkhSpaceId(address, chainId, this.spacePrefix);
571
583
  const secretsSpaceId = makePkhSpaceId(address, chainId, "secrets");
572
- return {
573
- abilities: this.defaultActions,
574
- spaceId: primarySpaceId2,
575
- spaceAbilities: {
576
- [primarySpaceId2]: this.defaultActions,
577
- [secretsSpaceId]: {
578
- kv: {
579
- "vault/secrets/": [
580
- KV.GET,
581
- KV.PUT,
582
- KV.DEL,
583
- KV.LIST,
584
- KV.METADATA
585
- ]
584
+ const primaryActions = this.includeAccountRegistryPermissions && this.spacePrefix === ACCOUNT_REGISTRY_SPACE ? cloneAbilitiesMap(this.defaultActions) : this.defaultActions;
585
+ const spaceAbilities2 = {
586
+ [primarySpaceId2]: primaryActions,
587
+ [secretsSpaceId]: {
588
+ kv: {
589
+ "vault/secrets/": [
590
+ KV.GET,
591
+ KV.PUT,
592
+ KV.DEL,
593
+ KV.LIST,
594
+ KV.METADATA
595
+ ]
596
+ }
597
+ }
598
+ };
599
+ if (this.includeAccountRegistryPermissions && this.spacePrefix !== ACCOUNT_REGISTRY_SPACE) {
600
+ spaceAbilities2[makePkhSpaceId(address, chainId, ACCOUNT_REGISTRY_SPACE)] = resourceCapabilitiesToAbilitiesMap(ACCOUNT_MANIFEST_PERMISSIONS);
601
+ } else if (this.includeAccountRegistryPermissions) {
602
+ const accountAbilities = resourceCapabilitiesToAbilitiesMap(
603
+ ACCOUNT_MANIFEST_PERMISSIONS
604
+ );
605
+ for (const [service, paths] of Object.entries(accountAbilities)) {
606
+ const existingPaths = primaryActions[service] ?? (primaryActions[service] = {});
607
+ for (const [path, actions] of Object.entries(paths)) {
608
+ const existingActions = existingPaths[path] ?? (existingPaths[path] = []);
609
+ for (const action of actions) {
610
+ if (!existingActions.includes(action)) existingActions.push(action);
586
611
  }
587
612
  }
588
- },
613
+ }
614
+ }
615
+ return {
616
+ abilities: primaryActions,
617
+ spaceId: primarySpaceId2,
618
+ spaceAbilities: spaceAbilities2,
589
619
  rawAbilities: {
590
620
  [defaultNetworkId]: [DECRYPT_ACTION, NETWORK_CREATE_ACTION]
591
621
  }
@@ -1649,12 +1679,14 @@ import {
1649
1679
  SharingService,
1650
1680
  UnsupportedFeatureError,
1651
1681
  makePublicSpaceId,
1652
- ACCOUNT_REGISTRY_SPACE,
1682
+ ACCOUNT_REGISTRY_SPACE as ACCOUNT_REGISTRY_SPACE2,
1683
+ BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST,
1653
1684
  BOOTSTRAP_SESSION_REQUESTS,
1654
1685
  SECRET_RECORDS_SCHEMA,
1655
1686
  SECRETS_SPACE as SECRETS_SPACE2,
1656
1687
  TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
1657
1688
  bootstrapSteps,
1689
+ ErrorCodes as ErrorCodes2,
1658
1690
  ENCRYPTION_PERMISSION_SERVICE as ENCRYPTION_PERMISSION_SERVICE2,
1659
1691
  CaveatedDelegationUnsupportedError,
1660
1692
  PermissionNotInManifestError,
@@ -2123,6 +2155,9 @@ var DEFAULT_HOST = "https://node.tinycloud.xyz";
2123
2155
  var DEFAULT_ENCRYPTION_NETWORK_NAME = "default";
2124
2156
  var NETWORK_CREATE_ACTION2 = ENCRYPTION2.NETWORK_CREATE;
2125
2157
  var DECRYPT_ACTION2 = ENCRYPTION2.DECRYPT;
2158
+ var BOOTSTRAP_COMPLETION_MARKER_KEY = "system/bootstrap/complete";
2159
+ var BOOTSTRAP_COMPLETION_MARKER_VERSION = 1;
2160
+ var ACCEPTED_MARKER_VERSIONS = [BOOTSTRAP_COMPLETION_MARKER_VERSION];
2126
2161
  var NETWORK_ADMIN_TYPE = "tinycloud.encryption.network-admin/v1";
2127
2162
  function isSecretPayload(value) {
2128
2163
  return typeof value === "object" && value !== null && "value" in value && typeof value.value === "string" && "createdAt" in value && typeof value.createdAt === "string" && "updatedAt" in value && typeof value.updatedAt === "string";
@@ -2530,9 +2565,12 @@ var _TinyCloudNode = class _TinyCloudNode {
2530
2565
  this._bootstrapSkipped = false;
2531
2566
  /**
2532
2567
  * Outcome of the last signIn()'s account-bootstrap attempt. `skipped` is
2533
- * true when bootstrap did not complete (interactive signer, auto-sign
2534
- * denied, or a bootstrap step failed); `reason` carries the cause so apps
2535
- * can surface a "finish account setup" call-to-action. `warnings` is
2568
+ * true when bootstrap did not complete in this invocation (interactive signer,
2569
+ * auto-bootstrap disabled, already provisioned, or a decision/provisioning
2570
+ * step failed). `already-provisioned` means the bootstrap was not run here;
2571
+ * it does not mean a prior provisioning attempt failed to complete.
2572
+ * `reason` carries the cause so apps can surface a "finish account setup"
2573
+ * call-to-action. `warnings` is
2536
2574
  * present when bootstrap completed, but one or more steps recovered from
2537
2575
  * an ambiguous failure (e.g. a KV batch write reconciled via per-space
2538
2576
  * fallback) — clean vs. recovered runs are otherwise byte-identical.
@@ -2715,7 +2753,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2715
2753
  nonce: config.nonce,
2716
2754
  siweConfig: config.siweConfig,
2717
2755
  manifest: useBootstrapSignInRequest ? void 0 : config.manifest,
2718
- capabilityRequest: useBootstrapSignInRequest ? BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
2756
+ capabilityRequest: useBootstrapSignInRequest ? config.includeAccountRegistryPermissions === false ? BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
2719
2757
  includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : config.includeAccountRegistryPermissions
2720
2758
  });
2721
2759
  this.tc = new TinyCloud(this.auth, {
@@ -2855,7 +2893,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2855
2893
  if (!this._address) {
2856
2894
  return void 0;
2857
2895
  }
2858
- return this.wasmBindings.makeSpaceId(this._address, this._chainId, ACCOUNT_REGISTRY_SPACE);
2896
+ return this.wasmBindings.makeSpaceId(this._address, this._chainId, ACCOUNT_REGISTRY_SPACE2);
2859
2897
  }
2860
2898
  /**
2861
2899
  * Account-level application and delegation helpers.
@@ -2958,6 +2996,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2958
2996
  this._bootstrapSkipped = false;
2959
2997
  this._bootstrapStatus = { skipped: false };
2960
2998
  if (this.config.autoBootstrapAccount === false) {
2999
+ this._bootstrapStatus = { skipped: true, reason: "auto-bootstrap-disabled" };
2961
3000
  return false;
2962
3001
  }
2963
3002
  if (!this.auth || !this._address) {
@@ -2972,11 +3011,14 @@ var _TinyCloudNode = class _TinyCloudNode {
2972
3011
  return false;
2973
3012
  }
2974
3013
  const steps = bootstrapSteps(this._address, this._chainId);
2975
- if (!await this.isFreshBootstrapAccount(steps)) {
2976
- return false;
2977
- }
2978
3014
  try {
2979
- const warnings = await this.runAccountBootstrap(steps);
3015
+ const decision = await this.resolveBootstrapDecision(steps);
3016
+ if (decision.action === "skip") {
3017
+ this._bootstrapStatus = { skipped: true, reason: "already-provisioned" };
3018
+ return false;
3019
+ }
3020
+ const warnings = await this.runAccountBootstrap(steps, { mode: decision.mode });
3021
+ await this.writeBootstrapCompletionMarker(steps);
2980
3022
  if (warnings.length > 0) {
2981
3023
  this._bootstrapStatus = { skipped: false, warnings };
2982
3024
  this.notificationHandler.warning(
@@ -2995,32 +3037,92 @@ var _TinyCloudNode = class _TinyCloudNode {
2995
3037
  }
2996
3038
  return true;
2997
3039
  }
2998
- async isFreshBootstrapAccount(steps) {
3040
+ async resolveBootstrapDecision(steps) {
2999
3041
  const enshrinedSpaceIds = /* @__PURE__ */ new Set();
3000
3042
  for (const step of steps) {
3001
3043
  if (step.kind === "session") {
3002
3044
  enshrinedSpaceIds.add(step.spaceId);
3003
3045
  }
3004
3046
  }
3005
- const skipped = this.auth.lastActivationSkippedSpaceIds;
3047
+ const auth = this.auth;
3048
+ if (!auth) {
3049
+ throw new Error("Account bootstrap requires an active wallet session");
3050
+ }
3051
+ const skipped = auth.lastActivationSkippedSpaceIds;
3006
3052
  if (skipped.some((spaceId) => enshrinedSpaceIds.has(spaceId))) {
3007
- return true;
3053
+ return { action: "run", mode: "fresh" };
3008
3054
  }
3009
3055
  try {
3010
- const indexed = await this.account.index.spaces.list();
3011
- if (indexed.ok && indexed.data.length === 0) {
3012
- return true;
3056
+ const accountSpaceId = this.ownedSpaceId(ACCOUNT_REGISTRY_SPACE2);
3057
+ const markerPermission = {
3058
+ service: "tinycloud.kv",
3059
+ space: accountSpaceId,
3060
+ path: BOOTSTRAP_COMPLETION_MARKER_KEY,
3061
+ actions: ["get"]
3062
+ };
3063
+ if (!this.hasRuntimePermissions([markerPermission])) {
3064
+ return { action: "run", mode: "repair" };
3013
3065
  }
3014
- } catch {
3066
+ const marker = await this.readBootstrapCompletionMarker();
3067
+ if (marker.ok) {
3068
+ if (this.isAcceptedBootstrapCompletionMarker(marker.data.data)) {
3069
+ return { action: "skip" };
3070
+ }
3071
+ return { action: "run", mode: "repair" };
3072
+ }
3073
+ if (marker.error.code === ErrorCodes2.KV_NOT_FOUND && this.markerReadIsUnhostedSpace(marker.error.meta)) {
3074
+ return { action: "run", mode: "fresh" };
3075
+ }
3076
+ } catch (err) {
3077
+ const reason = err instanceof Error ? err.message : String(err);
3078
+ this.notificationHandler.warning(
3079
+ `Account bootstrap decision failed; attempting one bounded repair: ${reason}`
3080
+ );
3081
+ console.warn(`[TinyCloudNode] account bootstrap decision failed: ${reason}`);
3082
+ return { action: "run", mode: "repair" };
3015
3083
  }
3016
- try {
3017
- const spaces = await this.account.spaces.list();
3018
- return spaces.ok && spaces.data.length === 0;
3019
- } catch {
3020
- return false;
3084
+ return { action: "run", mode: "repair" };
3085
+ }
3086
+ async readBootstrapCompletionMarker() {
3087
+ return this.kvForSpace(this.ownedSpaceId(ACCOUNT_REGISTRY_SPACE2)).get(
3088
+ BOOTSTRAP_COMPLETION_MARKER_KEY
3089
+ );
3090
+ }
3091
+ async writeBootstrapCompletionMarker(steps) {
3092
+ if (!this._address) {
3093
+ throw new Error("Bootstrap completion marker requires an active wallet session");
3094
+ }
3095
+ const canonicalStepIds = new Set(
3096
+ bootstrapSteps(this._address, this._chainId).map((step) => step.id)
3097
+ );
3098
+ const providedStepIds = new Set(steps.map((step) => step.id));
3099
+ if (canonicalStepIds.size !== providedStepIds.size || [...canonicalStepIds].some((stepId) => !providedStepIds.has(stepId))) {
3100
+ throw new Error("Bootstrap completion marker requires the canonical bootstrap step set");
3101
+ }
3102
+ const marker = {
3103
+ v: BOOTSTRAP_COMPLETION_MARKER_VERSION,
3104
+ stepIds: [...canonicalStepIds],
3105
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
3106
+ };
3107
+ const written = await this.kvForSpace(this.ownedSpaceId(ACCOUNT_REGISTRY_SPACE2)).put(
3108
+ BOOTSTRAP_COMPLETION_MARKER_KEY,
3109
+ marker
3110
+ );
3111
+ if (!written.ok) {
3112
+ throw new Error(`Failed to write bootstrap completion marker: ${written.error.message}`);
3021
3113
  }
3022
3114
  }
3023
- async runAccountBootstrap(steps) {
3115
+ isAcceptedBootstrapCompletionMarker(value) {
3116
+ if (typeof value !== "object" || value === null) return false;
3117
+ const entries = Object.entries(value);
3118
+ const markerValue = (name) => entries.find(([key]) => key === name)?.[1];
3119
+ const version = markerValue("v");
3120
+ return typeof version === "number" && Number.isInteger(version) && ACCEPTED_MARKER_VERSIONS.some((acceptedVersion) => acceptedVersion === version);
3121
+ }
3122
+ markerReadIsUnhostedSpace(meta) {
3123
+ return meta?.status === 404;
3124
+ }
3125
+ async runAccountBootstrap(steps, { mode } = { mode: "fresh" }) {
3024
3126
  if (!this.auth || !this._address) {
3025
3127
  throw new Error("Account bootstrap requires an active wallet session");
3026
3128
  }
@@ -3121,9 +3223,8 @@ var _TinyCloudNode = class _TinyCloudNode {
3121
3223
  if (step.kind === "seed-applications") {
3122
3224
  const registered = await this.account.applications.register(
3123
3225
  step.manifests.length > 0 ? [...step.manifests] : TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
3124
- // Bootstrap only runs on an account with no registry records, so the
3125
- // manifest-hash pre-read is definitionally a miss. Skip it; the write
3126
- // it guards is an INSERT OR REPLACE and is safe to repeat.
3226
+ // The write is an INSERT OR REPLACE and is safe to repeat during a
3227
+ // repair, so skip the manifest-hash pre-read.
3127
3228
  { assumeUnregistered: true }
3128
3229
  );
3129
3230
  if (!registered.ok) {
@@ -3131,7 +3232,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3131
3232
  }
3132
3233
  }
3133
3234
  if (step.kind === "encryption-network-create") {
3134
- await this.ensureEncryptionNetwork(step.networkId, { assumeMissing: true });
3235
+ await this.ensureEncryptionNetwork(step.networkId, { assumeMissing: mode === "fresh" });
3135
3236
  }
3136
3237
  if (step.kind === "secret-records-schema") {
3137
3238
  const db = this.sqlForSpace(step.spaceId).db(step.database);
@@ -3314,7 +3415,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3314
3415
  if (!this.auth || !this.signer) {
3315
3416
  throw new Error("Manifest registry write requires wallet mode");
3316
3417
  }
3317
- const accountSpaceId = this.ownedSpaceId(ACCOUNT_REGISTRY_SPACE);
3418
+ const accountSpaceId = this.ownedSpaceId(ACCOUNT_REGISTRY_SPACE2);
3318
3419
  await this.ensureOwnedSpaceHostedById(accountSpaceId);
3319
3420
  const result = await this.account.applications.register(request.manifests);
3320
3421
  if (!result.ok) {
@@ -4180,7 +4281,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4180
4281
  nonce: this.config.nonce,
4181
4282
  siweConfig: this.config.siweConfig,
4182
4283
  manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
4183
- capabilityRequest: useBootstrapSignInRequest ? BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
4284
+ capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
4184
4285
  includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
4185
4286
  });
4186
4287
  this.tc = new TinyCloud(this.auth, {
@@ -4233,7 +4334,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4233
4334
  nonce: this.config.nonce,
4234
4335
  siweConfig: this.config.siweConfig,
4235
4336
  manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
4236
- capabilityRequest: useBootstrapSignInRequest ? BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
4337
+ capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
4237
4338
  includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
4238
4339
  });
4239
4340
  this.tc = new TinyCloud(this.auth, {
@@ -6982,35 +7083,44 @@ var _TinyCloudNode = class _TinyCloudNode {
6982
7083
  if (parentDelegation.disableSubDelegation) {
6983
7084
  throw new Error("Parent delegation does not allow sub-delegation");
6984
7085
  }
6985
- if (!params.path.startsWith(parentDelegation.path)) {
7086
+ const parentResources = parentDelegation.resources ?? [{
7087
+ service: parentDelegation.actions[0]?.split("/", 1)[0]?.replace(/^tinycloud\./, "") ?? "kv",
7088
+ space: parentDelegation.spaceId,
7089
+ path: parentDelegation.path,
7090
+ actions: parentDelegation.actions
7091
+ }];
7092
+ const requestedResources = params.resources ?? [{
7093
+ service: params.actions[0]?.split("/", 1)[0]?.replace(/^tinycloud\./, "") ?? "kv",
7094
+ space: parentDelegation.spaceId,
7095
+ path: params.path,
7096
+ actions: params.actions
7097
+ }];
7098
+ const resourceIsContained = (parent, child) => {
7099
+ const parentEncryption = parent.service === "encryption" || parent.service === "tinycloud.encryption";
7100
+ const childEncryption = child.service === "encryption" || child.service === "tinycloud.encryption";
7101
+ if (parentEncryption || childEncryption) return parentEncryption && childEncryption && parent.path === child.path && child.actions.every((action) => parent.actions.includes(action));
7102
+ const pathContained = parent.path === child.path || parent.path.endsWith("/") && child.path.startsWith(parent.path) || child.path.startsWith(`${parent.path}/`);
7103
+ return pathContained && child.actions.every((action) => parent.actions.includes(action));
7104
+ };
7105
+ if (requestedResources.length === 0 || requestedResources.some((child) => !parentResources.some((parent) => resourceIsContained(parent, child)))) {
6986
7106
  throw new Error(
6987
- `Sub-delegation path "${params.path}" must be within parent path "${parentDelegation.path}"`
7107
+ "Sub-delegation resources exceed the received delegation"
6988
7108
  );
6989
7109
  }
6990
- const parentActions = new Set(parentDelegation.actions);
6991
- for (const action of params.actions) {
6992
- if (!parentActions.has(action)) {
6993
- throw new Error(
6994
- `Sub-delegation action "${action}" is not in parent's actions: ${parentDelegation.actions.join(", ")}`
6995
- );
6996
- }
6997
- }
6998
7110
  const now = /* @__PURE__ */ new Date();
6999
7111
  const expiryMs = params.expiryMs ?? 60 * 60 * 1e3;
7000
7112
  const requestedExpiry = new Date(now.getTime() + expiryMs);
7001
7113
  const actualExpiry = requestedExpiry > parentDelegation.expiry ? parentDelegation.expiry : requestedExpiry;
7002
7114
  const abilities = {};
7003
- const kvActions = params.actions.filter((a) => a.startsWith("tinycloud.kv/"));
7004
- const sqlActions = params.actions.filter((a) => a.startsWith("tinycloud.sql/"));
7005
- const duckdbActions = params.actions.filter((a) => a.startsWith("tinycloud.duckdb/"));
7006
- if (kvActions.length > 0) {
7007
- abilities.kv = { [params.path]: kvActions };
7008
- }
7009
- if (sqlActions.length > 0) {
7010
- abilities.sql = { [params.path]: sqlActions };
7011
- }
7012
- if (duckdbActions.length > 0) {
7013
- abilities.duckdb = { [params.path]: duckdbActions };
7115
+ const rawAbilities = {};
7116
+ for (const resource of requestedResources) {
7117
+ const service = resource.service.replace(/^tinycloud\./, "");
7118
+ if (service === "encryption") {
7119
+ rawAbilities[resource.path] = [...resource.actions];
7120
+ continue;
7121
+ }
7122
+ abilities[service] ?? (abilities[service] = {});
7123
+ abilities[service][resource.path] = [...resource.actions];
7014
7124
  }
7015
7125
  const targetHost = parentDelegation.host ?? this.config.host;
7016
7126
  const prepared = this.wasmBindings.prepareSession({
@@ -7022,7 +7132,8 @@ var _TinyCloudNode = class _TinyCloudNode {
7022
7132
  expirationTime: actualExpiry.toISOString(),
7023
7133
  spaceId: parentDelegation.spaceId,
7024
7134
  delegateUri: params.delegateDID,
7025
- parents: [parentDelegation.cid]
7135
+ parents: [parentDelegation.cid],
7136
+ ...Object.keys(rawAbilities).length > 0 ? { rawAbilities } : {}
7026
7137
  });
7027
7138
  const signature = await this.signer.signMessage(prepared.siwe);
7028
7139
  const subDelegationSession = this.wasmBindings.completeSessionSetup({
@@ -7040,14 +7151,20 @@ var _TinyCloudNode = class _TinyCloudNode {
7040
7151
  cid: subDelegationSession.delegationCid,
7041
7152
  delegationHeader: subDelegationSession.delegationHeader,
7042
7153
  spaceId: parentDelegation.spaceId,
7043
- path: params.path,
7044
- actions: params.actions,
7154
+ path: requestedResources[0].path,
7155
+ actions: requestedResources[0].actions,
7045
7156
  disableSubDelegation: params.disableSubDelegation ?? false,
7046
7157
  expiry: actualExpiry,
7047
7158
  delegateDID: params.delegateDID,
7048
7159
  ownerAddress: parentDelegation.ownerAddress,
7049
7160
  chainId: parentDelegation.chainId,
7050
- host: targetHost
7161
+ host: targetHost,
7162
+ resources: requestedResources.map((resource) => ({
7163
+ service: resource.service.replace(/^tinycloud\./, ""),
7164
+ space: resource.service.replace(/^tinycloud\./, "") === "encryption" ? "encryption" : resource.space ?? parentDelegation.spaceId,
7165
+ path: resource.path,
7166
+ actions: [...resource.actions]
7167
+ }))
7051
7168
  };
7052
7169
  }
7053
7170
  };
@@ -7067,7 +7184,7 @@ var TinyCloudNode = _TinyCloudNode;
7067
7184
  // src/core.ts
7068
7185
  import {
7069
7186
  ACCOUNT_REGISTRY_PATH,
7070
- ACCOUNT_REGISTRY_SPACE as ACCOUNT_REGISTRY_SPACE2,
7187
+ ACCOUNT_REGISTRY_SPACE as ACCOUNT_REGISTRY_SPACE3,
7071
7188
  DEFAULT_MANIFEST_SPACE as DEFAULT_MANIFEST_SPACE2,
7072
7189
  DEFAULT_MANIFEST_VERSION,
7073
7190
  VAULT_PERMISSION_SERVICE,
@@ -7159,7 +7276,7 @@ import {
7159
7276
  import { ServiceContext as ServiceContext3 } from "@tinycloud/sdk-core";
7160
7277
  export {
7161
7278
  ACCOUNT_REGISTRY_PATH,
7162
- ACCOUNT_REGISTRY_SPACE2 as ACCOUNT_REGISTRY_SPACE,
7279
+ ACCOUNT_REGISTRY_SPACE3 as ACCOUNT_REGISTRY_SPACE,
7163
7280
  AccountService,
7164
7281
  AutoApproveSpaceCreationHandler2 as AutoApproveSpaceCreationHandler,
7165
7282
  CapabilityKeyRegistry2 as CapabilityKeyRegistry,