@tinycloud/node-sdk 2.4.0-beta.9 → 2.4.1-beta.0
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-iwTdsebf.d.cts → core-D01sn2vf.d.cts} +134 -7
- package/dist/{core-iwTdsebf.d.ts → core-D01sn2vf.d.ts} +134 -7
- package/dist/core.cjs +810 -268
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +601 -54
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +853 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +601 -54
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -17173,6 +17173,11 @@ import {
|
|
|
17173
17173
|
UnsupportedFeatureError,
|
|
17174
17174
|
makePublicSpaceId,
|
|
17175
17175
|
ACCOUNT_REGISTRY_SPACE,
|
|
17176
|
+
BOOTSTRAP_SESSION_REQUESTS,
|
|
17177
|
+
SECRET_RECORDS_SCHEMA,
|
|
17178
|
+
SECRETS_SPACE as SECRETS_SPACE2,
|
|
17179
|
+
TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
|
|
17180
|
+
bootstrapSteps,
|
|
17176
17181
|
ENCRYPTION_PERMISSION_SERVICE as ENCRYPTION_PERMISSION_SERVICE2,
|
|
17177
17182
|
PermissionNotInManifestError,
|
|
17178
17183
|
SessionExpiredError,
|
|
@@ -17186,6 +17191,7 @@ import {
|
|
|
17186
17191
|
verifyDidKeyEd25519Signature,
|
|
17187
17192
|
canonicalizeAddress as canonicalizeAddress2,
|
|
17188
17193
|
pkhDid as pkhDid2,
|
|
17194
|
+
resolveTinyCloudHosts as resolveTinyCloudHosts2,
|
|
17189
17195
|
principalDidEquals as principalDidEquals2,
|
|
17190
17196
|
parseNetworkId as parseNetworkId2
|
|
17191
17197
|
} from "@tinycloud/sdk-core";
|
|
@@ -17212,6 +17218,7 @@ import {
|
|
|
17212
17218
|
} from "@tinycloud/sdk-core";
|
|
17213
17219
|
|
|
17214
17220
|
// src/authorization/strategies.ts
|
|
17221
|
+
import { createOpenKeyCallbackSigningStrategy } from "@tinycloud/sdk-core";
|
|
17215
17222
|
var defaultSignStrategy = { type: "auto-sign" };
|
|
17216
17223
|
|
|
17217
17224
|
// src/storage/MemorySessionStorage.ts
|
|
@@ -17309,6 +17316,7 @@ var NodeUserAuthorization = class {
|
|
|
17309
17316
|
constructor(config) {
|
|
17310
17317
|
this.extensions = [];
|
|
17311
17318
|
this._nodeFeatures = [];
|
|
17319
|
+
this._lastActivationSkippedSpaceIds = [];
|
|
17312
17320
|
this.wasm = config.wasmBindings;
|
|
17313
17321
|
this.signer = config.signer;
|
|
17314
17322
|
this.signStrategy = config.signStrategy ?? defaultSignStrategy;
|
|
@@ -17331,7 +17339,7 @@ var NodeUserAuthorization = class {
|
|
|
17331
17339
|
"": [
|
|
17332
17340
|
"tinycloud.sql/read",
|
|
17333
17341
|
"tinycloud.sql/write",
|
|
17334
|
-
"tinycloud.sql/
|
|
17342
|
+
"tinycloud.sql/schema",
|
|
17335
17343
|
"tinycloud.sql/admin",
|
|
17336
17344
|
"tinycloud.sql/export"
|
|
17337
17345
|
]
|
|
@@ -17423,12 +17431,48 @@ var NodeUserAuthorization = class {
|
|
|
17423
17431
|
* `siwe` is the load-bearing one because `extractSiweExpiration` returns
|
|
17424
17432
|
* undefined for missing SIWEs and the SDK then treats the session as
|
|
17425
17433
|
* expired-at-epoch-zero.
|
|
17434
|
+
*
|
|
17435
|
+
* @param hosts - The TinyCloud hosts this session was created against,
|
|
17436
|
+
* as persisted in {@link PersistedSessionData.tinycloudHosts}. When
|
|
17437
|
+
* present (and non-empty) they are adopted directly so the restored
|
|
17438
|
+
* session resolves to the same node as the original sign-in without
|
|
17439
|
+
* re-running registry/fallback resolution. When absent (old session)
|
|
17440
|
+
* hosts are resolved lazily on the first host-needing call via
|
|
17441
|
+
* {@link ensureTinyCloudHosts}.
|
|
17426
17442
|
*/
|
|
17427
|
-
setRestoredTinyCloudSession(session) {
|
|
17443
|
+
setRestoredTinyCloudSession(session, hosts) {
|
|
17428
17444
|
const address = canonicalizeAddress(session.address);
|
|
17429
17445
|
this._tinyCloudSession = { ...session, address };
|
|
17430
17446
|
this._address = address;
|
|
17431
17447
|
this._chainId = session.chainId;
|
|
17448
|
+
if ((!this.tinycloudHosts || this.tinycloudHosts.length === 0) && hosts && hosts.length > 0) {
|
|
17449
|
+
this.tinycloudHosts = [...hosts];
|
|
17450
|
+
}
|
|
17451
|
+
}
|
|
17452
|
+
/**
|
|
17453
|
+
* Ensure `tinycloudHosts` are resolved before a host-needing call.
|
|
17454
|
+
*
|
|
17455
|
+
* Fresh sign-in resolves hosts up front; a restored session may not have
|
|
17456
|
+
* (old persisted sessions predate {@link PersistedSessionData.tinycloudHosts}).
|
|
17457
|
+
* This guard makes a restored session resolve the node exactly like a fresh
|
|
17458
|
+
* sign-in — persisted hosts are preferred (already set by
|
|
17459
|
+
* {@link setRestoredTinyCloudSession}), otherwise the registry/fallback
|
|
17460
|
+
* resolution runs lazily here. Idempotent: {@link resolveTinyCloudHostsForSignIn}
|
|
17461
|
+
* early-returns when hosts are already set.
|
|
17462
|
+
*
|
|
17463
|
+
* Throws if hosts are unset and the restored session has no address/chainId
|
|
17464
|
+
* to resolve from — a real failure that must surface, not be masked.
|
|
17465
|
+
*/
|
|
17466
|
+
async ensureTinyCloudHosts() {
|
|
17467
|
+
if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
|
|
17468
|
+
return;
|
|
17469
|
+
}
|
|
17470
|
+
if (this._address === void 0 || this._chainId === void 0) {
|
|
17471
|
+
throw new Error(
|
|
17472
|
+
"Cannot resolve TinyCloud hosts: no address/chainId available. Sign in or restore a session first."
|
|
17473
|
+
);
|
|
17474
|
+
}
|
|
17475
|
+
await this.resolveTinyCloudHostsForSignIn(this._address, this._chainId);
|
|
17432
17476
|
}
|
|
17433
17477
|
async resolveTinyCloudHostsForSignIn(address, chainId) {
|
|
17434
17478
|
if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
|
|
@@ -17453,6 +17497,9 @@ var NodeUserAuthorization = class {
|
|
|
17453
17497
|
get nodeFeatures() {
|
|
17454
17498
|
return this._nodeFeatures;
|
|
17455
17499
|
}
|
|
17500
|
+
get lastActivationSkippedSpaceIds() {
|
|
17501
|
+
return [...this._lastActivationSkippedSpaceIds];
|
|
17502
|
+
}
|
|
17456
17503
|
/**
|
|
17457
17504
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
17458
17505
|
* see at sign-in time.
|
|
@@ -17625,6 +17672,7 @@ var NodeUserAuthorization = class {
|
|
|
17625
17672
|
if (!this._tinyCloudSession || !this._address || !this._chainId) {
|
|
17626
17673
|
throw new Error("Must be signed in to host space");
|
|
17627
17674
|
}
|
|
17675
|
+
await this.ensureTinyCloudHosts();
|
|
17628
17676
|
const host = this.primaryTinyCloudHost;
|
|
17629
17677
|
const spaceId = targetSpaceId ?? this._tinyCloudSession.spaceId;
|
|
17630
17678
|
const peerId = await fetchPeerId(host, spaceId);
|
|
@@ -17667,12 +17715,14 @@ var NodeUserAuthorization = class {
|
|
|
17667
17715
|
if (!this._tinyCloudSession) {
|
|
17668
17716
|
throw new Error("Must be signed in to ensure space exists");
|
|
17669
17717
|
}
|
|
17718
|
+
await this.ensureTinyCloudHosts();
|
|
17670
17719
|
const host = this.primaryTinyCloudHost;
|
|
17671
17720
|
const primarySpaceId = this._tinyCloudSession.spaceId;
|
|
17672
17721
|
const result = await activateSessionWithHost(
|
|
17673
17722
|
host,
|
|
17674
17723
|
this._tinyCloudSession.delegationHeader
|
|
17675
17724
|
);
|
|
17725
|
+
this.recordActivationSkippedSpaces(result, primarySpaceId);
|
|
17676
17726
|
const handler = this.spaceCreationHandler ?? (this.autoCreateSpace ? new AutoApproveSpaceCreationHandler() : void 0);
|
|
17677
17727
|
const creationContext = {
|
|
17678
17728
|
spaceId: primarySpaceId,
|
|
@@ -17760,6 +17810,66 @@ var NodeUserAuthorization = class {
|
|
|
17760
17810
|
}
|
|
17761
17811
|
throw new Error(`Failed to activate session: ${result.error}`);
|
|
17762
17812
|
}
|
|
17813
|
+
recordActivationSkippedSpaces(result, primarySpaceId) {
|
|
17814
|
+
if (result.success) {
|
|
17815
|
+
this._lastActivationSkippedSpaceIds = result.skipped ?? [];
|
|
17816
|
+
return;
|
|
17817
|
+
}
|
|
17818
|
+
this._lastActivationSkippedSpaceIds = result.status === 404 ? [primarySpaceId] : [];
|
|
17819
|
+
}
|
|
17820
|
+
async createBootstrapSession(options) {
|
|
17821
|
+
if (!this._address || !this._chainId) {
|
|
17822
|
+
throw new Error("Must be signed in before creating bootstrap sessions");
|
|
17823
|
+
}
|
|
17824
|
+
const address = this._address;
|
|
17825
|
+
const chainId = this._chainId;
|
|
17826
|
+
const keyId = `bootstrap-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
17827
|
+
this.sessionManager.createSessionKey(keyId);
|
|
17828
|
+
const jwkString = this.sessionManager.jwk(keyId);
|
|
17829
|
+
if (!jwkString) {
|
|
17830
|
+
throw new Error("Failed to create bootstrap session key");
|
|
17831
|
+
}
|
|
17832
|
+
const jwk = JSON.parse(jwkString);
|
|
17833
|
+
const now = /* @__PURE__ */ new Date();
|
|
17834
|
+
const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
|
|
17835
|
+
const abilities = resourceCapabilitiesToAbilitiesMap(
|
|
17836
|
+
options.capabilityRequest.resources
|
|
17837
|
+
);
|
|
17838
|
+
const prepared = this.wasm.prepareSession({
|
|
17839
|
+
abilities,
|
|
17840
|
+
...options.rawAbilities !== void 0 ? { rawAbilities: options.rawAbilities } : {},
|
|
17841
|
+
address,
|
|
17842
|
+
chainId,
|
|
17843
|
+
domain: this.domain,
|
|
17844
|
+
issuedAt: now.toISOString(),
|
|
17845
|
+
expirationTime: expirationTime.toISOString(),
|
|
17846
|
+
spaceId: options.spaceId,
|
|
17847
|
+
jwk,
|
|
17848
|
+
...this.buildSiweOverrides()
|
|
17849
|
+
});
|
|
17850
|
+
const signature2 = await this.requestSignature({
|
|
17851
|
+
address,
|
|
17852
|
+
chainId,
|
|
17853
|
+
message: prepared.siwe,
|
|
17854
|
+
type: "siwe"
|
|
17855
|
+
});
|
|
17856
|
+
const session = this.wasm.completeSessionSetup({
|
|
17857
|
+
...prepared,
|
|
17858
|
+
signature: signature2
|
|
17859
|
+
});
|
|
17860
|
+
return {
|
|
17861
|
+
address,
|
|
17862
|
+
chainId,
|
|
17863
|
+
sessionKey: keyId,
|
|
17864
|
+
spaceId: options.spaceId,
|
|
17865
|
+
delegationCid: session.delegationCid,
|
|
17866
|
+
delegationHeader: session.delegationHeader,
|
|
17867
|
+
verificationMethod: this.sessionManager.getDID(keyId),
|
|
17868
|
+
jwk,
|
|
17869
|
+
siwe: prepared.siwe,
|
|
17870
|
+
signature: signature2
|
|
17871
|
+
};
|
|
17872
|
+
}
|
|
17763
17873
|
/**
|
|
17764
17874
|
* Sign in and create a new session.
|
|
17765
17875
|
*
|
|
@@ -17848,7 +17958,8 @@ var NodeUserAuthorization = class {
|
|
|
17848
17958
|
},
|
|
17849
17959
|
expiresAt: expirationTime.toISOString(),
|
|
17850
17960
|
createdAt: now.toISOString(),
|
|
17851
|
-
version: "1.0"
|
|
17961
|
+
version: "1.0",
|
|
17962
|
+
tinycloudHosts: this.tinycloudHosts
|
|
17852
17963
|
};
|
|
17853
17964
|
await this.sessionStorage.save(address, persistedData);
|
|
17854
17965
|
this._session = clientSession;
|
|
@@ -18015,7 +18126,8 @@ var NodeUserAuthorization = class {
|
|
|
18015
18126
|
},
|
|
18016
18127
|
expiresAt,
|
|
18017
18128
|
createdAt,
|
|
18018
|
-
version: "1.0"
|
|
18129
|
+
version: "1.0",
|
|
18130
|
+
tinycloudHosts: this.tinycloudHosts
|
|
18019
18131
|
};
|
|
18020
18132
|
await this.sessionStorage.save(address, persistedData);
|
|
18021
18133
|
this._session = clientSession;
|
|
@@ -18117,12 +18229,13 @@ import {
|
|
|
18117
18229
|
ServiceContext
|
|
18118
18230
|
} from "@tinycloud/sdk-core";
|
|
18119
18231
|
var DelegatedAccess = class {
|
|
18120
|
-
constructor(session, delegation, host, invoke2, telemetry) {
|
|
18232
|
+
constructor(session, delegation, host, invoke2, invokeAny2, telemetry) {
|
|
18121
18233
|
this.session = session;
|
|
18122
18234
|
this._delegation = delegation;
|
|
18123
18235
|
this.host = host;
|
|
18124
18236
|
this._serviceContext = new ServiceContext({
|
|
18125
18237
|
invoke: invoke2,
|
|
18238
|
+
invokeAny: invokeAny2,
|
|
18126
18239
|
fetch: globalThis.fetch.bind(globalThis),
|
|
18127
18240
|
hosts: [host],
|
|
18128
18241
|
telemetry
|
|
@@ -18389,12 +18502,12 @@ function displayActionUrn(action) {
|
|
|
18389
18502
|
function secretActionName(action) {
|
|
18390
18503
|
return action;
|
|
18391
18504
|
}
|
|
18392
|
-
function secretPermissionEntries(name, options, action, encryptionNetworkId) {
|
|
18505
|
+
function secretPermissionEntries(name, options, action, space, encryptionNetworkId) {
|
|
18393
18506
|
const entries = [];
|
|
18394
18507
|
const path = action === "list" ? resolveSecretListPrefix(options) : resolveSecretPath(name, options).permissionPaths.vault;
|
|
18395
18508
|
entries.push({
|
|
18396
18509
|
service: "tinycloud.kv",
|
|
18397
|
-
space
|
|
18510
|
+
space,
|
|
18398
18511
|
path,
|
|
18399
18512
|
actions: [secretActionName(action)],
|
|
18400
18513
|
skipPrefix: true
|
|
@@ -18409,11 +18522,23 @@ function secretPermissionEntries(name, options, action, encryptionNetworkId) {
|
|
|
18409
18522
|
}
|
|
18410
18523
|
return entries;
|
|
18411
18524
|
}
|
|
18525
|
+
function normalizeSpace(space, resolveSpace) {
|
|
18526
|
+
if (!space) return void 0;
|
|
18527
|
+
if (space.startsWith("tinycloud:")) return space;
|
|
18528
|
+
return resolveSpace?.(space) ?? space;
|
|
18529
|
+
}
|
|
18530
|
+
function spaceMatches(granted, requested, resolveSpace) {
|
|
18531
|
+
if (!granted || !requested) return false;
|
|
18532
|
+
return normalizeSpace(granted, resolveSpace) === normalizeSpace(requested, resolveSpace);
|
|
18533
|
+
}
|
|
18412
18534
|
var NodeSecretsService = class {
|
|
18413
18535
|
constructor(config) {
|
|
18414
18536
|
this.config = config;
|
|
18415
18537
|
this.shouldRestoreUnlock = false;
|
|
18416
18538
|
}
|
|
18539
|
+
get space() {
|
|
18540
|
+
return this.config.space ?? SECRETS_SPACE;
|
|
18541
|
+
}
|
|
18417
18542
|
get vault() {
|
|
18418
18543
|
return this.service.vault;
|
|
18419
18544
|
}
|
|
@@ -18466,6 +18591,7 @@ var NodeSecretsService = class {
|
|
|
18466
18591
|
name,
|
|
18467
18592
|
options,
|
|
18468
18593
|
action,
|
|
18594
|
+
this.space,
|
|
18469
18595
|
action === "get" ? this.config.getEncryptionNetworkId?.() : void 0
|
|
18470
18596
|
);
|
|
18471
18597
|
} catch (error) {
|
|
@@ -18515,7 +18641,7 @@ var NodeSecretsService = class {
|
|
|
18515
18641
|
(entry) => manifests.some((candidate) => {
|
|
18516
18642
|
const resolved = resolveManifest(candidate);
|
|
18517
18643
|
return resolved.resources.some(
|
|
18518
|
-
(resource) => resource.service === entry.service && resource.space
|
|
18644
|
+
(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))
|
|
18519
18645
|
);
|
|
18520
18646
|
})
|
|
18521
18647
|
);
|
|
@@ -18529,6 +18655,9 @@ var NETWORK_CREATE_ACTION2 = "tinycloud.encryption/network.create";
|
|
|
18529
18655
|
var DECRYPT_ACTION2 = "tinycloud.encryption/decrypt";
|
|
18530
18656
|
var NETWORK_ADMIN_TYPE = "tinycloud.encryption.network-admin/v1";
|
|
18531
18657
|
var DEFAULT_SESSION_EXPIRATION_MS = EXPIRY3.SESSION_MS;
|
|
18658
|
+
function isOpenKeyAutoSignStrategy(strategy) {
|
|
18659
|
+
return strategy?.openKeyAutoSign === true;
|
|
18660
|
+
}
|
|
18532
18661
|
function didPrincipalMatches2(actual, expected) {
|
|
18533
18662
|
try {
|
|
18534
18663
|
return principalDidEquals2(actual, expected);
|
|
@@ -18536,6 +18665,20 @@ function didPrincipalMatches2(actual, expected) {
|
|
|
18536
18665
|
return actual === expected;
|
|
18537
18666
|
}
|
|
18538
18667
|
}
|
|
18668
|
+
function sharingActionsToAbilities(path, actions) {
|
|
18669
|
+
var _a;
|
|
18670
|
+
const abilities = {};
|
|
18671
|
+
for (const action of actions) {
|
|
18672
|
+
const slash = action.indexOf("/");
|
|
18673
|
+
if (slash === -1) return void 0;
|
|
18674
|
+
const shortService = SERVICE_LONG_TO_SHORT[action.slice(0, slash)];
|
|
18675
|
+
if (shortService === void 0) return void 0;
|
|
18676
|
+
abilities[shortService] ?? (abilities[shortService] = {});
|
|
18677
|
+
(_a = abilities[shortService])[path] ?? (_a[path] = []);
|
|
18678
|
+
abilities[shortService][path].push(action);
|
|
18679
|
+
}
|
|
18680
|
+
return Object.keys(abilities).length > 0 ? abilities : void 0;
|
|
18681
|
+
}
|
|
18539
18682
|
function base64UrlEncode(bytes) {
|
|
18540
18683
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
18541
18684
|
let output = "";
|
|
@@ -18648,6 +18791,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18648
18791
|
this.auth = null;
|
|
18649
18792
|
this.tc = null;
|
|
18650
18793
|
this._chainId = 1;
|
|
18794
|
+
this._baseSecrets = /* @__PURE__ */ new Map();
|
|
18795
|
+
this._secrets = /* @__PURE__ */ new Map();
|
|
18651
18796
|
this.runtimePermissionGrants = [];
|
|
18652
18797
|
this.invokeWithRuntimePermissions = (session, service, path, action, facts) => {
|
|
18653
18798
|
return this.wasmBindings.invoke(
|
|
@@ -18753,9 +18898,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18753
18898
|
* @internal
|
|
18754
18899
|
*/
|
|
18755
18900
|
setupAuth(config) {
|
|
18901
|
+
const useBootstrapSignInRequest = this.shouldUseBootstrapSignInRequest(config);
|
|
18756
18902
|
this.auth = new NodeUserAuthorization({
|
|
18757
18903
|
signer: this.signer,
|
|
18758
|
-
signStrategy: { type: "auto-sign" },
|
|
18904
|
+
signStrategy: config.signStrategy ?? { type: "auto-sign" },
|
|
18759
18905
|
wasmBindings: this.wasmBindings,
|
|
18760
18906
|
sessionStorage: config.sessionStorage ?? new MemorySessionStorage(),
|
|
18761
18907
|
domain: this.siweDomain,
|
|
@@ -18764,20 +18910,23 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18764
18910
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
18765
18911
|
tinycloudRegistryUrl: config.tinycloudRegistryUrl,
|
|
18766
18912
|
tinycloudFallbackHosts: config.tinycloudFallbackHosts,
|
|
18767
|
-
autoCreateSpace: config.autoCreateSpace,
|
|
18913
|
+
autoCreateSpace: useBootstrapSignInRequest ? false : config.autoCreateSpace,
|
|
18768
18914
|
enablePublicSpace: config.enablePublicSpace ?? true,
|
|
18769
|
-
spaceCreationHandler: config.spaceCreationHandler,
|
|
18915
|
+
spaceCreationHandler: useBootstrapSignInRequest ? void 0 : config.spaceCreationHandler,
|
|
18770
18916
|
nonce: config.nonce,
|
|
18771
18917
|
siweConfig: config.siweConfig,
|
|
18772
|
-
manifest: config.manifest,
|
|
18773
|
-
capabilityRequest: config.capabilityRequest,
|
|
18774
|
-
includeAccountRegistryPermissions: config.includeAccountRegistryPermissions
|
|
18918
|
+
manifest: useBootstrapSignInRequest ? void 0 : config.manifest,
|
|
18919
|
+
capabilityRequest: useBootstrapSignInRequest ? BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
|
|
18920
|
+
includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : config.includeAccountRegistryPermissions
|
|
18775
18921
|
});
|
|
18776
18922
|
this.tc = new TinyCloud(this.auth, {
|
|
18777
18923
|
invokeAny: this.invokeAnyWithRuntimePermissions,
|
|
18778
18924
|
telemetry: config.telemetry
|
|
18779
18925
|
});
|
|
18780
18926
|
}
|
|
18927
|
+
shouldUseBootstrapSignInRequest(config) {
|
|
18928
|
+
return config.autoBootstrapAccount !== false && config.manifest === void 0 && config.capabilityRequest === void 0 && (config.prefix ?? "default") === "default" && isOpenKeyAutoSignStrategy(config.signStrategy);
|
|
18929
|
+
}
|
|
18781
18930
|
syncResolvedHostFromAuth() {
|
|
18782
18931
|
const host = this.auth?.hosts[0];
|
|
18783
18932
|
if (host) {
|
|
@@ -18892,7 +19041,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18892
19041
|
getAccountDb: () => this.accountSpaceId ? this.sqlForSpace(this.accountSpaceId).db("account") : void 0,
|
|
18893
19042
|
ensureAccountSpaceHosted: async () => {
|
|
18894
19043
|
if (this.accountSpaceId && this.auth) {
|
|
18895
|
-
await this.
|
|
19044
|
+
await this.ensureOwnedSpaceHostedById(this.accountSpaceId);
|
|
18896
19045
|
}
|
|
18897
19046
|
}
|
|
18898
19047
|
});
|
|
@@ -18906,6 +19055,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18906
19055
|
get session() {
|
|
18907
19056
|
return this.auth?.tinyCloudSession;
|
|
18908
19057
|
}
|
|
19058
|
+
/**
|
|
19059
|
+
* Get the currently active session in the shape callers can persist and later
|
|
19060
|
+
* pass back to {@link restoreSession}.
|
|
19061
|
+
*/
|
|
19062
|
+
get restorableSession() {
|
|
19063
|
+
return this.currentTinyCloudSession();
|
|
19064
|
+
}
|
|
18909
19065
|
/**
|
|
18910
19066
|
* Sign in and create a new session.
|
|
18911
19067
|
* This creates the user's space if it doesn't exist.
|
|
@@ -18928,19 +19084,22 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18928
19084
|
this._hooks = void 0;
|
|
18929
19085
|
this._vault = void 0;
|
|
18930
19086
|
this._encryption = void 0;
|
|
18931
|
-
this._baseSecrets
|
|
18932
|
-
this._secrets
|
|
19087
|
+
this._baseSecrets.clear();
|
|
19088
|
+
this._secrets.clear();
|
|
18933
19089
|
this._spaceService = void 0;
|
|
18934
19090
|
this._serviceContext = void 0;
|
|
18935
19091
|
this.runtimePermissionGrants = [];
|
|
18936
19092
|
await this.tc.signIn(options);
|
|
18937
19093
|
this.syncResolvedHostFromAuth();
|
|
18938
19094
|
this.initializeServices();
|
|
19095
|
+
const bootstrapped = await this.bootstrapAccountIfNeeded();
|
|
18939
19096
|
await this.ensureRequestedEncryptionNetworks();
|
|
18940
|
-
if (this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
|
|
18941
|
-
await this.
|
|
19097
|
+
if (!bootstrapped && this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
|
|
19098
|
+
await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(SECRETS_SPACE2));
|
|
19099
|
+
}
|
|
19100
|
+
if (!bootstrapped) {
|
|
19101
|
+
this.scheduleAccountRegistrySync();
|
|
18942
19102
|
}
|
|
18943
|
-
this.scheduleAccountRegistrySync();
|
|
18944
19103
|
this.notificationHandler.success("Successfully signed in");
|
|
18945
19104
|
}
|
|
18946
19105
|
ownedSpaceId(name) {
|
|
@@ -18949,6 +19108,208 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18949
19108
|
}
|
|
18950
19109
|
return this.wasmBindings.makeSpaceId(this._address, this._chainId, name);
|
|
18951
19110
|
}
|
|
19111
|
+
async bootstrapAccountIfNeeded() {
|
|
19112
|
+
if (this.config.autoBootstrapAccount === false) {
|
|
19113
|
+
return false;
|
|
19114
|
+
}
|
|
19115
|
+
if (!this.auth || !this._address) {
|
|
19116
|
+
return false;
|
|
19117
|
+
}
|
|
19118
|
+
const steps = bootstrapSteps(this._address, this._chainId);
|
|
19119
|
+
if (!await this.isFreshBootstrapAccount(steps)) {
|
|
19120
|
+
return false;
|
|
19121
|
+
}
|
|
19122
|
+
await this.runAccountBootstrap(steps);
|
|
19123
|
+
return true;
|
|
19124
|
+
}
|
|
19125
|
+
async isFreshBootstrapAccount(steps) {
|
|
19126
|
+
const enshrinedSpaceIds = /* @__PURE__ */ new Set();
|
|
19127
|
+
for (const step of steps) {
|
|
19128
|
+
if (step.kind === "session") {
|
|
19129
|
+
enshrinedSpaceIds.add(step.spaceId);
|
|
19130
|
+
}
|
|
19131
|
+
}
|
|
19132
|
+
const skipped = this.auth.lastActivationSkippedSpaceIds;
|
|
19133
|
+
if (skipped.some((spaceId) => enshrinedSpaceIds.has(spaceId))) {
|
|
19134
|
+
return true;
|
|
19135
|
+
}
|
|
19136
|
+
try {
|
|
19137
|
+
const indexed = await this.account.index.spaces.list();
|
|
19138
|
+
if (indexed.ok && indexed.data.length === 0) {
|
|
19139
|
+
return true;
|
|
19140
|
+
}
|
|
19141
|
+
} catch {
|
|
19142
|
+
}
|
|
19143
|
+
try {
|
|
19144
|
+
const spaces = await this.account.spaces.list();
|
|
19145
|
+
return spaces.ok && spaces.data.length === 0;
|
|
19146
|
+
} catch {
|
|
19147
|
+
return false;
|
|
19148
|
+
}
|
|
19149
|
+
}
|
|
19150
|
+
async runAccountBootstrap(steps) {
|
|
19151
|
+
if (!this.auth || !this._address) {
|
|
19152
|
+
throw new Error("Account bootstrap requires an active wallet session");
|
|
19153
|
+
}
|
|
19154
|
+
const host = this.hosts[0] ?? this.config.host;
|
|
19155
|
+
if (!host) {
|
|
19156
|
+
throw new Error("Account bootstrap requires a TinyCloud host");
|
|
19157
|
+
}
|
|
19158
|
+
const auth = this.auth;
|
|
19159
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
19160
|
+
const rawAbilitiesBySpace = /* @__PURE__ */ new Map();
|
|
19161
|
+
const primarySession = auth.tinyCloudSession;
|
|
19162
|
+
const defaultSpaceId = this.ownedSpaceId("default");
|
|
19163
|
+
const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === BOOTSTRAP_SESSION_REQUESTS.default;
|
|
19164
|
+
for (const step of steps) {
|
|
19165
|
+
if (step.kind !== "session") continue;
|
|
19166
|
+
if (step.space === "default" && canReusePrimaryBootstrapSession && primarySession) {
|
|
19167
|
+
sessions.set(step.space, primarySession);
|
|
19168
|
+
continue;
|
|
19169
|
+
}
|
|
19170
|
+
const rawAbilities = step.rawAbilities;
|
|
19171
|
+
if (rawAbilities) {
|
|
19172
|
+
rawAbilitiesBySpace.set(step.space, rawAbilities);
|
|
19173
|
+
}
|
|
19174
|
+
const session = await auth.createBootstrapSession({
|
|
19175
|
+
spaceId: step.spaceId,
|
|
19176
|
+
capabilityRequest: step.request ?? BOOTSTRAP_SESSION_REQUESTS[step.space],
|
|
19177
|
+
rawAbilities
|
|
19178
|
+
});
|
|
19179
|
+
sessions.set(step.space, session);
|
|
19180
|
+
}
|
|
19181
|
+
for (const step of steps) {
|
|
19182
|
+
if (step.kind !== "host") continue;
|
|
19183
|
+
const hosted = await auth.hostOwnedSpace(step.spaceId);
|
|
19184
|
+
if (!hosted) {
|
|
19185
|
+
throw new Error(`Failed to host bootstrap space: ${step.spaceId}`);
|
|
19186
|
+
}
|
|
19187
|
+
}
|
|
19188
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
19189
|
+
for (const step of steps) {
|
|
19190
|
+
if (step.kind !== "activate") continue;
|
|
19191
|
+
const session = sessions.get(step.space);
|
|
19192
|
+
if (!session) {
|
|
19193
|
+
throw new Error(`Missing bootstrap session for ${step.space}`);
|
|
19194
|
+
}
|
|
19195
|
+
const activated = await activateSessionWithHost2(host, session.delegationHeader);
|
|
19196
|
+
if (!activated.success || activated.skipped?.includes(step.spaceId)) {
|
|
19197
|
+
throw new Error(
|
|
19198
|
+
`Failed to activate bootstrap session for ${step.spaceId}: ${activated.error ?? "space was skipped"}`
|
|
19199
|
+
);
|
|
19200
|
+
}
|
|
19201
|
+
this.registerBootstrapRuntimeGrant(
|
|
19202
|
+
session,
|
|
19203
|
+
BOOTSTRAP_SESSION_REQUESTS[step.space],
|
|
19204
|
+
rawAbilitiesBySpace.get(step.space)
|
|
19205
|
+
);
|
|
19206
|
+
}
|
|
19207
|
+
for (const step of steps) {
|
|
19208
|
+
if (step.kind === "account-index-schema") {
|
|
19209
|
+
const ensured = await this.account.index.ensure();
|
|
19210
|
+
if (!ensured.ok) {
|
|
19211
|
+
throw new Error(`Failed to create account index schema: ${ensured.error.message}`);
|
|
19212
|
+
}
|
|
19213
|
+
}
|
|
19214
|
+
if (step.kind === "seed-spaces") {
|
|
19215
|
+
for (const space of step.spaces) {
|
|
19216
|
+
const registered = await this.account.spaces.register({
|
|
19217
|
+
spaceId: space.spaceId,
|
|
19218
|
+
name: space.name,
|
|
19219
|
+
ownerDid: this.did,
|
|
19220
|
+
type: "owned",
|
|
19221
|
+
permissions: ["*"],
|
|
19222
|
+
status: "active"
|
|
19223
|
+
});
|
|
19224
|
+
if (!registered.ok) {
|
|
19225
|
+
throw new Error(
|
|
19226
|
+
`Failed to seed account space ${space.spaceId}: ${registered.error.message}`
|
|
19227
|
+
);
|
|
19228
|
+
}
|
|
19229
|
+
}
|
|
19230
|
+
}
|
|
19231
|
+
if (step.kind === "seed-applications") {
|
|
19232
|
+
const registered = await this.account.applications.register(
|
|
19233
|
+
step.manifests.length > 0 ? [...step.manifests] : TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST
|
|
19234
|
+
);
|
|
19235
|
+
if (!registered.ok) {
|
|
19236
|
+
throw new Error(`Failed to seed bootstrap applications: ${registered.error.message}`);
|
|
19237
|
+
}
|
|
19238
|
+
}
|
|
19239
|
+
if (step.kind === "encryption-network-create") {
|
|
19240
|
+
await this.ensureEncryptionNetwork(step.networkId);
|
|
19241
|
+
}
|
|
19242
|
+
if (step.kind === "secret-records-schema") {
|
|
19243
|
+
const db = this.sqlForSpace(step.spaceId).db(step.database);
|
|
19244
|
+
const migrated = await db.migrations.apply({
|
|
19245
|
+
namespace: "tinycloud.secrets.records",
|
|
19246
|
+
migrations: [
|
|
19247
|
+
{
|
|
19248
|
+
id: "001_initial",
|
|
19249
|
+
sql: [...SECRET_RECORDS_SCHEMA]
|
|
19250
|
+
}
|
|
19251
|
+
]
|
|
19252
|
+
});
|
|
19253
|
+
if (!migrated.ok) {
|
|
19254
|
+
throw new Error(
|
|
19255
|
+
`Failed to create secret_records schema: ${migrated.error.message}`
|
|
19256
|
+
);
|
|
19257
|
+
}
|
|
19258
|
+
}
|
|
19259
|
+
}
|
|
19260
|
+
}
|
|
19261
|
+
registerBootstrapRuntimeGrant(session, request, rawAbilities) {
|
|
19262
|
+
const operations = [];
|
|
19263
|
+
for (const resource of request.resources) {
|
|
19264
|
+
const service = resource.service.startsWith("tinycloud.") ? this.shortServiceName(resource.service) : resource.service;
|
|
19265
|
+
const spaceId = resource.space.startsWith("tinycloud:") ? resource.space : this.ownedSpaceId(resource.space);
|
|
19266
|
+
for (const action of resource.actions) {
|
|
19267
|
+
operations.push({
|
|
19268
|
+
spaceId,
|
|
19269
|
+
service,
|
|
19270
|
+
path: resource.path,
|
|
19271
|
+
action
|
|
19272
|
+
});
|
|
19273
|
+
}
|
|
19274
|
+
}
|
|
19275
|
+
for (const [resource, actions2] of Object.entries(rawAbilities ?? {})) {
|
|
19276
|
+
for (const action of actions2) {
|
|
19277
|
+
operations.push({
|
|
19278
|
+
resource,
|
|
19279
|
+
service: "encryption",
|
|
19280
|
+
path: resource,
|
|
19281
|
+
action
|
|
19282
|
+
});
|
|
19283
|
+
}
|
|
19284
|
+
}
|
|
19285
|
+
const expiresAt = extractSiweExpiration(session.siwe) ?? this.getSessionExpiry();
|
|
19286
|
+
const actions = [...new Set(operations.map((operation) => operation.action))];
|
|
19287
|
+
this.runtimePermissionGrants.push({
|
|
19288
|
+
session: {
|
|
19289
|
+
delegationHeader: session.delegationHeader,
|
|
19290
|
+
delegationCid: session.delegationCid,
|
|
19291
|
+
spaceId: session.spaceId,
|
|
19292
|
+
verificationMethod: session.verificationMethod,
|
|
19293
|
+
jwk: session.jwk
|
|
19294
|
+
},
|
|
19295
|
+
delegation: {
|
|
19296
|
+
cid: session.delegationCid,
|
|
19297
|
+
delegationHeader: session.delegationHeader,
|
|
19298
|
+
delegateDID: session.verificationMethod,
|
|
19299
|
+
delegatorDID: this.did,
|
|
19300
|
+
spaceId: session.spaceId,
|
|
19301
|
+
path: "",
|
|
19302
|
+
actions,
|
|
19303
|
+
expiry: expiresAt,
|
|
19304
|
+
allowSubDelegation: true,
|
|
19305
|
+
ownerAddress: session.address,
|
|
19306
|
+
chainId: session.chainId,
|
|
19307
|
+
host: this.config.host
|
|
19308
|
+
},
|
|
19309
|
+
operations,
|
|
19310
|
+
expiresAt
|
|
19311
|
+
});
|
|
19312
|
+
}
|
|
18952
19313
|
async writeManifestRegistryRecords() {
|
|
18953
19314
|
const request = this.capabilityRequest;
|
|
18954
19315
|
if (!request || request.registryRecords.length === 0) {
|
|
@@ -18958,7 +19319,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18958
19319
|
throw new Error("Manifest registry write requires wallet mode");
|
|
18959
19320
|
}
|
|
18960
19321
|
const accountSpaceId = this.ownedSpaceId(ACCOUNT_REGISTRY_SPACE);
|
|
18961
|
-
await this.
|
|
19322
|
+
await this.ensureOwnedSpaceHostedById(accountSpaceId);
|
|
18962
19323
|
const result = await this.account.applications.register(request.manifests);
|
|
18963
19324
|
if (!result.ok) {
|
|
18964
19325
|
throw new Error(
|
|
@@ -18968,6 +19329,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18968
19329
|
}
|
|
18969
19330
|
scheduleAccountRegistrySync() {
|
|
18970
19331
|
void this.withAccountRegistryRetry(async () => {
|
|
19332
|
+
void this.account.index.ensure();
|
|
18971
19333
|
await this.writeManifestRegistryRecords();
|
|
18972
19334
|
const spaces = await this.account.spaces.syncAccessible();
|
|
18973
19335
|
if (!spaces.ok) {
|
|
@@ -19019,7 +19381,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19019
19381
|
await this.ensureEncryptionNetwork(networkId);
|
|
19020
19382
|
}
|
|
19021
19383
|
}
|
|
19022
|
-
async
|
|
19384
|
+
async ensureOwnedSpaceHostedById(spaceId) {
|
|
19023
19385
|
if (!this.auth) {
|
|
19024
19386
|
throw new Error("Owned space hosting requires wallet mode");
|
|
19025
19387
|
}
|
|
@@ -19062,7 +19424,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19062
19424
|
* caller is the root authority of their own owned spaces, so no additional
|
|
19063
19425
|
* delegation is required.
|
|
19064
19426
|
*
|
|
19065
|
-
* Unlike {@link
|
|
19427
|
+
* Unlike {@link ensureOwnedSpaceHostedById}, this always submits the host
|
|
19066
19428
|
* delegation rather than inferring hosting from session activation: a space
|
|
19067
19429
|
* the current session has never referenced is reported neither as
|
|
19068
19430
|
* `activated` nor `skipped`, so activation-based detection would wrongly
|
|
@@ -19107,6 +19469,91 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19107
19469
|
});
|
|
19108
19470
|
return spaceId;
|
|
19109
19471
|
}
|
|
19472
|
+
/**
|
|
19473
|
+
* Ensure one of this user's owned spaces (e.g. `"secrets"`) is hosted on the
|
|
19474
|
+
* server.
|
|
19475
|
+
*
|
|
19476
|
+
* At sign-in, a full-authority session auto-hosts the owner's `secrets`
|
|
19477
|
+
* space, but a session created with a manifest / capabilityRequest does not.
|
|
19478
|
+
* Such a session can therefore hold valid `tinycloud.kv/*` capabilities for
|
|
19479
|
+
* the owned `secrets` space yet still fail its first scoped
|
|
19480
|
+
* `secrets.put(...)` with `404 Space not found`, because the space was never
|
|
19481
|
+
* registered on the node.
|
|
19482
|
+
*
|
|
19483
|
+
* Calling this resolves `name` to the owner's owned-space URI
|
|
19484
|
+
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It first consults the
|
|
19485
|
+
* account-space spaces registry (`account/spaces/{space_id}`, the canonical
|
|
19486
|
+
* KV source of truth, fronted by a best-effort SQLite index): if the space is
|
|
19487
|
+
* already registered/hosted it returns the URI WITHOUT submitting a host
|
|
19488
|
+
* delegation, avoiding a redundant host-SIWE signature prompt for owners who
|
|
19489
|
+
* already use the space. Only when the space is absent — or the registry
|
|
19490
|
+
* check fails for any reason (e.g. a cold SQLite index reporting
|
|
19491
|
+
* `no such table: spaces`) — does it fall through to {@link hostOwnedSpace}.
|
|
19492
|
+
*
|
|
19493
|
+
* The registry check is purely an optimization: any failure falls back to
|
|
19494
|
+
* hosting, and the host SIWE is idempotent server-side, so re-hosting an
|
|
19495
|
+
* existing space remains a safe no-op. Must be called after {@link signIn}.
|
|
19496
|
+
*
|
|
19497
|
+
* @param name - The owned space name (e.g. `"secrets"`).
|
|
19498
|
+
* @returns The hosted owned-space URI.
|
|
19499
|
+
*/
|
|
19500
|
+
async ensureOwnedSpaceHosted(name) {
|
|
19501
|
+
if (!this.auth || !this.auth.tinyCloudSession) {
|
|
19502
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
19503
|
+
}
|
|
19504
|
+
const spaceId = this.ownedSpaceId(name);
|
|
19505
|
+
if (await this.isOwnedSpaceRegistered(spaceId)) {
|
|
19506
|
+
return spaceId;
|
|
19507
|
+
}
|
|
19508
|
+
const hosted = await this.hostOwnedSpace(name);
|
|
19509
|
+
try {
|
|
19510
|
+
await this.account.spaces.register({
|
|
19511
|
+
spaceId,
|
|
19512
|
+
name,
|
|
19513
|
+
ownerDid: this.did,
|
|
19514
|
+
type: "owned",
|
|
19515
|
+
permissions: ["*"],
|
|
19516
|
+
status: "active"
|
|
19517
|
+
});
|
|
19518
|
+
} catch {
|
|
19519
|
+
}
|
|
19520
|
+
return hosted;
|
|
19521
|
+
}
|
|
19522
|
+
/**
|
|
19523
|
+
* Check whether an owned space is already registered/hosted by consulting the
|
|
19524
|
+
* account spaces registry.
|
|
19525
|
+
*
|
|
19526
|
+
* Source of truth is the canonical KV registry record
|
|
19527
|
+
* `account/spaces/{space_id}`, read here via `account.spaces.get(spaceId)`.
|
|
19528
|
+
* The KV path is used (rather than `syncAccessible()`) because it works under
|
|
19529
|
+
* a manifest/recap session with NO extra prompt: the composed manifest recap
|
|
19530
|
+
* already grants `tinycloud.kv get/list` on the account space `spaces/`
|
|
19531
|
+
* prefix, whereas `syncAccessible()` depends on `tinycloud.space/list`, which
|
|
19532
|
+
* a recap session does not hold. Before reading, it consults the fast SQLite
|
|
19533
|
+
* index (`account.index.spaces.list()`) as a best-effort short-circuit; on a
|
|
19534
|
+
* cold index (`no such table: spaces`) or any other index failure it falls
|
|
19535
|
+
* back to the canonical KV read.
|
|
19536
|
+
*
|
|
19537
|
+
* This is a best-effort optimization. ANY failure of the check path (missing
|
|
19538
|
+
* table, KV error, missing record, thrown exception) resolves to `false` so
|
|
19539
|
+
* the caller falls through to hosting — per the directive, "if it fails in any
|
|
19540
|
+
* way then create the space".
|
|
19541
|
+
*/
|
|
19542
|
+
async isOwnedSpaceRegistered(spaceId) {
|
|
19543
|
+
try {
|
|
19544
|
+
const indexed = await this.account.index.spaces.list();
|
|
19545
|
+
if (indexed.ok && indexed.data.some((space) => space.spaceId === spaceId)) {
|
|
19546
|
+
return true;
|
|
19547
|
+
}
|
|
19548
|
+
} catch {
|
|
19549
|
+
}
|
|
19550
|
+
try {
|
|
19551
|
+
const record = await this.account.spaces.get(spaceId);
|
|
19552
|
+
return record.ok;
|
|
19553
|
+
} catch {
|
|
19554
|
+
return false;
|
|
19555
|
+
}
|
|
19556
|
+
}
|
|
19110
19557
|
/**
|
|
19111
19558
|
* Restore a previously established session from stored delegation data.
|
|
19112
19559
|
*
|
|
@@ -19124,8 +19571,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19124
19571
|
this._hooks = void 0;
|
|
19125
19572
|
this._vault = void 0;
|
|
19126
19573
|
this._encryption = void 0;
|
|
19127
|
-
this._baseSecrets
|
|
19128
|
-
this._secrets
|
|
19574
|
+
this._baseSecrets.clear();
|
|
19575
|
+
this._secrets.clear();
|
|
19129
19576
|
this._spaceService = void 0;
|
|
19130
19577
|
this._serviceContext = void 0;
|
|
19131
19578
|
this.runtimePermissionGrants = [];
|
|
@@ -19136,6 +19583,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19136
19583
|
if (sessionData.chainId) {
|
|
19137
19584
|
this._chainId = sessionData.chainId;
|
|
19138
19585
|
}
|
|
19586
|
+
const resolvedHost = await this.resolveRestoredHost(
|
|
19587
|
+
sessionData.tinycloudHosts,
|
|
19588
|
+
restoredAddress,
|
|
19589
|
+
sessionData.chainId
|
|
19590
|
+
);
|
|
19591
|
+
if (resolvedHost) {
|
|
19592
|
+
this.config.host = resolvedHost;
|
|
19593
|
+
}
|
|
19139
19594
|
this._serviceContext = new ServiceContext2({
|
|
19140
19595
|
invoke: this.invokeWithRuntimePermissions,
|
|
19141
19596
|
invokeAny: this.invokeAnyWithRuntimePermissions,
|
|
@@ -19181,12 +19636,45 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19181
19636
|
signature: sessionData.signature ?? ""
|
|
19182
19637
|
};
|
|
19183
19638
|
if (this.auth) {
|
|
19184
|
-
this.auth.setRestoredTinyCloudSession(
|
|
19639
|
+
this.auth.setRestoredTinyCloudSession(
|
|
19640
|
+
tcSession,
|
|
19641
|
+
this.config.host ? [this.config.host] : void 0
|
|
19642
|
+
);
|
|
19185
19643
|
} else {
|
|
19186
19644
|
this._restoredTcSession = tcSession;
|
|
19187
19645
|
}
|
|
19188
19646
|
}
|
|
19189
19647
|
}
|
|
19648
|
+
/**
|
|
19649
|
+
* Resolve the host a restored session should target.
|
|
19650
|
+
*
|
|
19651
|
+
* Mirrors fresh sign-in host resolution but for the restore path:
|
|
19652
|
+
* an explicit/pinned host always wins, then the hosts the session was
|
|
19653
|
+
* persisted with, then a lazy registry/fallback resolution for sessions
|
|
19654
|
+
* that predate the persisted `tinycloudHosts` field. Returns `undefined`
|
|
19655
|
+
* only when there's nothing to resolve from (no explicit host, no
|
|
19656
|
+
* persisted hosts, and no address/chainId) — in which case the existing
|
|
19657
|
+
* `config.host` (default) is left in place.
|
|
19658
|
+
*
|
|
19659
|
+
* Resolution failures are surfaced, not swallowed: a genuinely broken
|
|
19660
|
+
* registry lookup throws rather than silently falling back to a wrong host.
|
|
19661
|
+
*/
|
|
19662
|
+
async resolveRestoredHost(persistedHosts, address, chainId) {
|
|
19663
|
+
if (this.explicitHost) {
|
|
19664
|
+
return this.explicitHost;
|
|
19665
|
+
}
|
|
19666
|
+
if (persistedHosts && persistedHosts.length > 0) {
|
|
19667
|
+
return persistedHosts[0];
|
|
19668
|
+
}
|
|
19669
|
+
if (address === void 0 || chainId === void 0) {
|
|
19670
|
+
return void 0;
|
|
19671
|
+
}
|
|
19672
|
+
const resolved = await resolveTinyCloudHosts2(pkhDid2(address, chainId), {
|
|
19673
|
+
registryUrl: this.config.tinycloudRegistryUrl,
|
|
19674
|
+
fallbackHosts: this.config.tinycloudFallbackHosts
|
|
19675
|
+
});
|
|
19676
|
+
return resolved.hosts[0];
|
|
19677
|
+
}
|
|
19190
19678
|
/**
|
|
19191
19679
|
* Resolve the currently-active TinyCloudSession, preferring the auth
|
|
19192
19680
|
* layer's value (wallet mode) and falling back to the node-level
|
|
@@ -19231,9 +19719,11 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19231
19719
|
);
|
|
19232
19720
|
}
|
|
19233
19721
|
this.signer = _TinyCloudNode.nodeDefaults.createSigner(privateKey);
|
|
19722
|
+
const authConfig = { ...this.config, prefix };
|
|
19723
|
+
const useBootstrapSignInRequest = this.shouldUseBootstrapSignInRequest(authConfig);
|
|
19234
19724
|
this.auth = new NodeUserAuthorization({
|
|
19235
19725
|
signer: this.signer,
|
|
19236
|
-
signStrategy: { type: "auto-sign" },
|
|
19726
|
+
signStrategy: this.config.signStrategy ?? { type: "auto-sign" },
|
|
19237
19727
|
wasmBindings: this.wasmBindings,
|
|
19238
19728
|
sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
|
|
19239
19729
|
domain: this.siweDomain,
|
|
@@ -19242,14 +19732,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19242
19732
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
19243
19733
|
tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
|
|
19244
19734
|
tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
|
|
19245
|
-
autoCreateSpace: this.config.autoCreateSpace,
|
|
19735
|
+
autoCreateSpace: useBootstrapSignInRequest ? false : this.config.autoCreateSpace,
|
|
19246
19736
|
enablePublicSpace: this.config.enablePublicSpace ?? true,
|
|
19247
|
-
spaceCreationHandler: this.config.spaceCreationHandler,
|
|
19737
|
+
spaceCreationHandler: useBootstrapSignInRequest ? void 0 : this.config.spaceCreationHandler,
|
|
19248
19738
|
nonce: this.config.nonce,
|
|
19249
19739
|
siweConfig: this.config.siweConfig,
|
|
19250
|
-
manifest: this.config.manifest,
|
|
19251
|
-
capabilityRequest: this.config.capabilityRequest,
|
|
19252
|
-
includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
|
|
19740
|
+
manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
|
|
19741
|
+
capabilityRequest: useBootstrapSignInRequest ? BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
|
|
19742
|
+
includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
|
|
19253
19743
|
});
|
|
19254
19744
|
this.tc = new TinyCloud(this.auth, {
|
|
19255
19745
|
invokeAny: this.invokeAnyWithRuntimePermissions,
|
|
@@ -19276,9 +19766,11 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19276
19766
|
}
|
|
19277
19767
|
const prefix = options?.prefix ?? "default";
|
|
19278
19768
|
this.signer = signer;
|
|
19769
|
+
const authConfig = { ...this.config, prefix };
|
|
19770
|
+
const useBootstrapSignInRequest = this.shouldUseBootstrapSignInRequest(authConfig);
|
|
19279
19771
|
this.auth = new NodeUserAuthorization({
|
|
19280
19772
|
signer: this.signer,
|
|
19281
|
-
signStrategy: { type: "auto-sign" },
|
|
19773
|
+
signStrategy: this.config.signStrategy ?? { type: "auto-sign" },
|
|
19282
19774
|
wasmBindings: this.wasmBindings,
|
|
19283
19775
|
sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
|
|
19284
19776
|
domain: this.siweDomain,
|
|
@@ -19287,14 +19779,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19287
19779
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
19288
19780
|
tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
|
|
19289
19781
|
tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
|
|
19290
|
-
autoCreateSpace: this.config.autoCreateSpace,
|
|
19782
|
+
autoCreateSpace: useBootstrapSignInRequest ? false : this.config.autoCreateSpace,
|
|
19291
19783
|
enablePublicSpace: this.config.enablePublicSpace ?? true,
|
|
19292
|
-
spaceCreationHandler: this.config.spaceCreationHandler,
|
|
19784
|
+
spaceCreationHandler: useBootstrapSignInRequest ? void 0 : this.config.spaceCreationHandler,
|
|
19293
19785
|
nonce: this.config.nonce,
|
|
19294
19786
|
siweConfig: this.config.siweConfig,
|
|
19295
|
-
manifest: this.config.manifest,
|
|
19296
|
-
capabilityRequest: this.config.capabilityRequest,
|
|
19297
|
-
includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
|
|
19787
|
+
manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
|
|
19788
|
+
capabilityRequest: useBootstrapSignInRequest ? BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
|
|
19789
|
+
includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
|
|
19298
19790
|
});
|
|
19299
19791
|
this.tc = new TinyCloud(this.auth, {
|
|
19300
19792
|
invokeAny: this.invokeAnyWithRuntimePermissions,
|
|
@@ -19370,6 +19862,20 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19370
19862
|
getDefaultEncryptionNetworkId(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
19371
19863
|
return `urn:tinycloud:encryption:${this.did}:${name}`;
|
|
19372
19864
|
}
|
|
19865
|
+
getEncryptionNetworkIdForSpace(spaceId, name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
19866
|
+
const ownerDid = this.ownerDidFromSpaceId(spaceId) ?? this.did;
|
|
19867
|
+
return `urn:tinycloud:encryption:${ownerDid}:${name}`;
|
|
19868
|
+
}
|
|
19869
|
+
ownerDidFromSpaceId(spaceId) {
|
|
19870
|
+
if (!spaceId.startsWith("tinycloud:")) return void 0;
|
|
19871
|
+
const body = spaceId.slice("tinycloud:".length);
|
|
19872
|
+
const lastSeparator = body.lastIndexOf(":");
|
|
19873
|
+
if (lastSeparator <= 0) return void 0;
|
|
19874
|
+
const owner = body.slice(0, lastSeparator);
|
|
19875
|
+
if (owner.startsWith("did:")) return owner;
|
|
19876
|
+
if (!owner.includes(":")) return void 0;
|
|
19877
|
+
return `did:${owner}`;
|
|
19878
|
+
}
|
|
19373
19879
|
requireServiceSession() {
|
|
19374
19880
|
const session = this._serviceContext?.session;
|
|
19375
19881
|
if (!session) {
|
|
@@ -19557,7 +20063,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19557
20063
|
spaceId,
|
|
19558
20064
|
crypto: vaultCrypto,
|
|
19559
20065
|
encryption: {
|
|
19560
|
-
networkId: this.
|
|
20066
|
+
networkId: this.getEncryptionNetworkIdForSpace(spaceId),
|
|
19561
20067
|
service: this.getEncryptionService(),
|
|
19562
20068
|
decryptCapabilityProof: () => ({
|
|
19563
20069
|
proofs: [this.requireServiceSession().delegationCid]
|
|
@@ -19688,6 +20194,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19688
20194
|
}
|
|
19689
20195
|
return vaultService;
|
|
19690
20196
|
},
|
|
20197
|
+
createSecretsService: (spaceId) => {
|
|
20198
|
+
return this.secretsForSpace(spaceId);
|
|
20199
|
+
},
|
|
19691
20200
|
// Enable space.delegations.create() via SIWE-based delegation
|
|
19692
20201
|
createDelegation: async (params) => {
|
|
19693
20202
|
try {
|
|
@@ -19810,11 +20319,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19810
20319
|
try {
|
|
19811
20320
|
const host = this.config.host;
|
|
19812
20321
|
const now = /* @__PURE__ */ new Date();
|
|
19813
|
-
const abilities =
|
|
19814
|
-
|
|
19815
|
-
|
|
19816
|
-
|
|
19817
|
-
};
|
|
20322
|
+
const abilities = sharingActionsToAbilities(params.path, params.actions);
|
|
20323
|
+
if (!abilities) {
|
|
20324
|
+
return void 0;
|
|
20325
|
+
}
|
|
19818
20326
|
const prepared = this.wasmBindings.prepareSession({
|
|
19819
20327
|
abilities,
|
|
19820
20328
|
address: this.wasmBindings.ensureEip55(session.address),
|
|
@@ -20070,27 +20578,49 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20070
20578
|
if (!this._spaceService) {
|
|
20071
20579
|
throw new Error("Not signed in. Call signIn() first.");
|
|
20072
20580
|
}
|
|
20073
|
-
|
|
20074
|
-
|
|
20075
|
-
|
|
20581
|
+
return this.secretsForSpace("secrets");
|
|
20582
|
+
}
|
|
20583
|
+
/**
|
|
20584
|
+
* App-facing secrets API backed by the requested space's vault.
|
|
20585
|
+
*/
|
|
20586
|
+
secretsForSpace(spaceId) {
|
|
20587
|
+
if (!this._spaceService) {
|
|
20588
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
20589
|
+
}
|
|
20590
|
+
const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
|
|
20591
|
+
let secrets = this._secrets.get(resolvedSpace);
|
|
20592
|
+
if (!secrets) {
|
|
20593
|
+
secrets = new NodeSecretsService({
|
|
20594
|
+
getService: () => this.getBaseSecrets(resolvedSpace),
|
|
20595
|
+
space: resolvedSpace,
|
|
20076
20596
|
getManifest: () => this.manifest,
|
|
20077
20597
|
hasPermissions: (permissions) => this.hasRuntimePermissions(permissions),
|
|
20078
20598
|
grantPermissions: (additional) => this.grantRuntimePermissions(additional),
|
|
20079
20599
|
canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
|
|
20080
|
-
getEncryptionNetworkId: () => this.
|
|
20600
|
+
getEncryptionNetworkId: () => this.getEncryptionNetworkIdForSpace(resolvedSpace),
|
|
20601
|
+
resolveSpace: (space) => space.startsWith("tinycloud:") ? space : this.ownedSpaceId(space),
|
|
20081
20602
|
getUnlockSigner: () => this.signer ?? void 0
|
|
20082
20603
|
});
|
|
20604
|
+
this._secrets.set(resolvedSpace, secrets);
|
|
20083
20605
|
}
|
|
20084
|
-
return
|
|
20606
|
+
return secrets;
|
|
20085
20607
|
}
|
|
20086
|
-
getBaseSecrets() {
|
|
20608
|
+
getBaseSecrets(spaceId) {
|
|
20087
20609
|
if (!this._spaceService) {
|
|
20088
20610
|
throw new Error("Not signed in. Call signIn() first.");
|
|
20089
20611
|
}
|
|
20090
|
-
|
|
20091
|
-
|
|
20612
|
+
const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
|
|
20613
|
+
let secrets = this._baseSecrets.get(resolvedSpace);
|
|
20614
|
+
if (!secrets) {
|
|
20615
|
+
const kvService = this.createSpaceScopedKVService(resolvedSpace);
|
|
20616
|
+
const vaultService = this.createVaultService(resolvedSpace, kvService);
|
|
20617
|
+
if (this._serviceContext) {
|
|
20618
|
+
vaultService.initialize(this._serviceContext);
|
|
20619
|
+
}
|
|
20620
|
+
secrets = new SecretsService(() => vaultService);
|
|
20621
|
+
this._baseSecrets.set(resolvedSpace, secrets);
|
|
20092
20622
|
}
|
|
20093
|
-
return
|
|
20623
|
+
return secrets;
|
|
20094
20624
|
}
|
|
20095
20625
|
/**
|
|
20096
20626
|
* Hooks write stream subscription API.
|
|
@@ -21504,6 +22034,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21504
22034
|
delegation,
|
|
21505
22035
|
targetHost,
|
|
21506
22036
|
this.wasmBindings.invoke,
|
|
22037
|
+
this.wasmBindings.invokeAny,
|
|
21507
22038
|
this.config.telemetry
|
|
21508
22039
|
);
|
|
21509
22040
|
}
|
|
@@ -21569,6 +22100,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21569
22100
|
delegation,
|
|
21570
22101
|
targetHost,
|
|
21571
22102
|
this.wasmBindings.invoke,
|
|
22103
|
+
this.wasmBindings.invokeAny,
|
|
21572
22104
|
this.config.telemetry
|
|
21573
22105
|
);
|
|
21574
22106
|
}
|
|
@@ -21700,7 +22232,14 @@ import {
|
|
|
21700
22232
|
pkhDid as pkhDid3,
|
|
21701
22233
|
principalDid,
|
|
21702
22234
|
principalDidEquals as principalDidEquals3,
|
|
21703
|
-
parseCanonicalNetworkId
|
|
22235
|
+
parseCanonicalNetworkId,
|
|
22236
|
+
TinyCloudDebugLogger,
|
|
22237
|
+
tinyCloudDebugLogger,
|
|
22238
|
+
enableTinyCloudDebug,
|
|
22239
|
+
disableTinyCloudDebug,
|
|
22240
|
+
getTinyCloudDebugLogs,
|
|
22241
|
+
clearTinyCloudDebugLogs,
|
|
22242
|
+
installTinyCloudDebugGlobals
|
|
21704
22243
|
} from "@tinycloud/sdk-core";
|
|
21705
22244
|
|
|
21706
22245
|
// src/storage/FileSessionStorage.ts
|
|
@@ -22034,6 +22573,7 @@ export {
|
|
|
22034
22573
|
SpaceErrorCodes,
|
|
22035
22574
|
SpaceService2 as SpaceService,
|
|
22036
22575
|
TinyCloud2 as TinyCloud,
|
|
22576
|
+
TinyCloudDebugLogger,
|
|
22037
22577
|
TinyCloudNode,
|
|
22038
22578
|
UnsupportedFeatureError2 as UnsupportedFeatureError,
|
|
22039
22579
|
VAULT_PERMISSION_SERVICE,
|
|
@@ -22058,8 +22598,10 @@ export {
|
|
|
22058
22598
|
canonicalizeSecretScope,
|
|
22059
22599
|
checkDecryptInvocationInput,
|
|
22060
22600
|
checkNodeInfo2 as checkNodeInfo,
|
|
22601
|
+
clearTinyCloudDebugLogs,
|
|
22061
22602
|
composeManifestRequest2 as composeManifestRequest,
|
|
22062
22603
|
createCapabilityKeyRegistry,
|
|
22604
|
+
createOpenKeyCallbackSigningStrategy,
|
|
22063
22605
|
createSharingService,
|
|
22064
22606
|
createSpaceService,
|
|
22065
22607
|
createVaultCrypto2 as createVaultCrypto,
|
|
@@ -22071,7 +22613,9 @@ export {
|
|
|
22071
22613
|
deserializeDelegation,
|
|
22072
22614
|
didCacheKey,
|
|
22073
22615
|
didEquals,
|
|
22616
|
+
disableTinyCloudDebug,
|
|
22074
22617
|
discoverNetwork,
|
|
22618
|
+
enableTinyCloudDebug,
|
|
22075
22619
|
encryptToNetwork,
|
|
22076
22620
|
encryptionBase64Decode,
|
|
22077
22621
|
encryptionBase64Encode,
|
|
@@ -22083,9 +22627,11 @@ export {
|
|
|
22083
22627
|
expandPermissionEntries2 as expandPermissionEntries,
|
|
22084
22628
|
expandPermissionEntry,
|
|
22085
22629
|
generateRandomReceiverKey,
|
|
22630
|
+
getTinyCloudDebugLogs,
|
|
22086
22631
|
grantAuthRequest,
|
|
22087
22632
|
hexDecode,
|
|
22088
22633
|
hexEncode,
|
|
22634
|
+
installTinyCloudDebugGlobals,
|
|
22089
22635
|
isCapabilitySubset2 as isCapabilitySubset,
|
|
22090
22636
|
isEvmAddress,
|
|
22091
22637
|
isNetworkId,
|
|
@@ -22107,6 +22653,7 @@ export {
|
|
|
22107
22653
|
resolveSecretPath2 as resolveSecretPath,
|
|
22108
22654
|
resourceCapabilitiesToSpaceAbilitiesMap2 as resourceCapabilitiesToSpaceAbilitiesMap,
|
|
22109
22655
|
serializeDelegation,
|
|
22656
|
+
tinyCloudDebugLogger,
|
|
22110
22657
|
validateEnvelope,
|
|
22111
22658
|
validateManifest,
|
|
22112
22659
|
verifyDecryptResponse
|