@tinycloud/node-sdk 2.2.0-beta.8 → 2.2.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-DcJ27GsA.d.cts → core-CNyXnUx9.d.cts} +80 -6
- package/dist/{core-DcJ27GsA.d.ts → core-CNyXnUx9.d.ts} +80 -6
- package/dist/core.cjs +717 -105
- 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 +736 -113
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +811 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +815 -114
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -17031,6 +17031,7 @@ var require_utils2 = __commonJS({
|
|
|
17031
17031
|
import {
|
|
17032
17032
|
invoke,
|
|
17033
17033
|
invokeAny,
|
|
17034
|
+
computeCid,
|
|
17034
17035
|
prepareSession,
|
|
17035
17036
|
completeSessionSetup,
|
|
17036
17037
|
ensureEip55,
|
|
@@ -17054,6 +17055,7 @@ var _NodeWasmBindings = class _NodeWasmBindings {
|
|
|
17054
17055
|
constructor() {
|
|
17055
17056
|
this.invoke = invoke;
|
|
17056
17057
|
this.invokeAny = invokeAny;
|
|
17058
|
+
this.computeCid = computeCid;
|
|
17057
17059
|
this.prepareSession = prepareSession;
|
|
17058
17060
|
this.completeSessionSetup = completeSessionSetup;
|
|
17059
17061
|
this.ensureEip55 = ensureEip55;
|
|
@@ -17159,6 +17161,7 @@ import {
|
|
|
17159
17161
|
DuckDbService as DuckDbService2,
|
|
17160
17162
|
HooksService as HooksService2,
|
|
17161
17163
|
DataVaultService,
|
|
17164
|
+
EncryptionService,
|
|
17162
17165
|
SecretsService,
|
|
17163
17166
|
createVaultCrypto,
|
|
17164
17167
|
ServiceContext as ServiceContext2,
|
|
@@ -17170,12 +17173,17 @@ import {
|
|
|
17170
17173
|
UnsupportedFeatureError,
|
|
17171
17174
|
makePublicSpaceId,
|
|
17172
17175
|
ACCOUNT_REGISTRY_SPACE,
|
|
17176
|
+
ENCRYPTION_PERMISSION_SERVICE as ENCRYPTION_PERMISSION_SERVICE2,
|
|
17173
17177
|
PermissionNotInManifestError,
|
|
17174
17178
|
SessionExpiredError,
|
|
17175
|
-
|
|
17179
|
+
expandPermissionEntries as expandPermissionEntriesCore,
|
|
17176
17180
|
isCapabilitySubset,
|
|
17177
17181
|
parseRecapCapabilities,
|
|
17178
|
-
SERVICE_LONG_TO_SHORT
|
|
17182
|
+
SERVICE_LONG_TO_SHORT,
|
|
17183
|
+
EXPIRY as EXPIRY3,
|
|
17184
|
+
canonicalHashHex,
|
|
17185
|
+
canonicalizeEncryptionJson,
|
|
17186
|
+
verifyDidKeyEd25519Signature
|
|
17179
17187
|
} from "@tinycloud/sdk-core";
|
|
17180
17188
|
|
|
17181
17189
|
// src/authorization/NodeUserAuthorization.ts
|
|
@@ -17186,10 +17194,12 @@ import {
|
|
|
17186
17194
|
checkNodeInfo,
|
|
17187
17195
|
AutoApproveSpaceCreationHandler,
|
|
17188
17196
|
DEFAULT_MANIFEST_SPACE,
|
|
17197
|
+
ENCRYPTION_PERMISSION_SERVICE,
|
|
17189
17198
|
composeManifestRequest,
|
|
17190
17199
|
resourceCapabilitiesToAbilitiesMap,
|
|
17191
17200
|
resourceCapabilitiesToSpaceAbilitiesMap,
|
|
17192
|
-
resolveTinyCloudHosts
|
|
17201
|
+
resolveTinyCloudHosts,
|
|
17202
|
+
EXPIRY
|
|
17193
17203
|
} from "@tinycloud/sdk-core";
|
|
17194
17204
|
|
|
17195
17205
|
// src/authorization/strategies.ts
|
|
@@ -17320,7 +17330,7 @@ var NodeUserAuthorization = class {
|
|
|
17320
17330
|
]
|
|
17321
17331
|
}
|
|
17322
17332
|
};
|
|
17323
|
-
this.sessionExpirationMs = config.sessionExpirationMs ??
|
|
17333
|
+
this.sessionExpirationMs = config.sessionExpirationMs ?? EXPIRY.SESSION_MS;
|
|
17324
17334
|
this.autoCreateSpace = config.autoCreateSpace ?? false;
|
|
17325
17335
|
this.spaceCreationHandler = config.spaceCreationHandler;
|
|
17326
17336
|
this.tinycloudHosts = config.tinycloudHosts;
|
|
@@ -17373,6 +17383,23 @@ var NodeUserAuthorization = class {
|
|
|
17373
17383
|
get tinyCloudSession() {
|
|
17374
17384
|
return this._tinyCloudSession;
|
|
17375
17385
|
}
|
|
17386
|
+
/**
|
|
17387
|
+
* Rehydrate the auth-layer session from previously-persisted delegation
|
|
17388
|
+
* data. Used by {@link TinyCloudNode.restoreSession} so that downstream
|
|
17389
|
+
* surfaces that read from `tinyCloudSession` (notably
|
|
17390
|
+
* `grantRuntimePermissions`, which extracts the SIWE expiry from it) work
|
|
17391
|
+
* without re-running the full sign-in flow.
|
|
17392
|
+
*
|
|
17393
|
+
* Caller must supply the same fields that `signIn` would have written —
|
|
17394
|
+
* `siwe` is the load-bearing one because `extractSiweExpiration` returns
|
|
17395
|
+
* undefined for missing SIWEs and the SDK then treats the session as
|
|
17396
|
+
* expired-at-epoch-zero.
|
|
17397
|
+
*/
|
|
17398
|
+
setRestoredTinyCloudSession(session) {
|
|
17399
|
+
this._tinyCloudSession = session;
|
|
17400
|
+
this._address = session.address;
|
|
17401
|
+
this._chainId = session.chainId;
|
|
17402
|
+
}
|
|
17376
17403
|
async resolveTinyCloudHostsForSignIn(address, chainId) {
|
|
17377
17404
|
if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
|
|
17378
17405
|
return;
|
|
@@ -17443,21 +17470,64 @@ var NodeUserAuthorization = class {
|
|
|
17443
17470
|
}
|
|
17444
17471
|
return this.wasm.makeSpaceId(address, chainId, space);
|
|
17445
17472
|
}
|
|
17473
|
+
defaultEncryptionNetworkId(address, chainId) {
|
|
17474
|
+
return `urn:tinycloud:encryption:did:pkh:eip155:${chainId}:${address}:default`;
|
|
17475
|
+
}
|
|
17446
17476
|
resolveSignInCapabilities(address, chainId) {
|
|
17447
17477
|
const request = this.getCapabilityRequest();
|
|
17448
17478
|
if (request === void 0) {
|
|
17479
|
+
const defaultNetworkId = this.defaultEncryptionNetworkId(address, chainId);
|
|
17480
|
+
const secretsSpaceId = this.wasm.makeSpaceId(address, chainId, "secrets");
|
|
17449
17481
|
return {
|
|
17450
17482
|
abilities: this.defaultActions,
|
|
17451
|
-
spaceId: this.wasm.makeSpaceId(address, chainId, this.spacePrefix)
|
|
17483
|
+
spaceId: this.wasm.makeSpaceId(address, chainId, this.spacePrefix),
|
|
17484
|
+
spaceAbilities: {
|
|
17485
|
+
[secretsSpaceId]: {
|
|
17486
|
+
kv: {
|
|
17487
|
+
"vault/secrets/": [
|
|
17488
|
+
"tinycloud.kv/get",
|
|
17489
|
+
"tinycloud.kv/put",
|
|
17490
|
+
"tinycloud.kv/del",
|
|
17491
|
+
"tinycloud.kv/list",
|
|
17492
|
+
"tinycloud.kv/metadata"
|
|
17493
|
+
]
|
|
17494
|
+
}
|
|
17495
|
+
}
|
|
17496
|
+
},
|
|
17497
|
+
rawAbilities: {
|
|
17498
|
+
[defaultNetworkId]: [
|
|
17499
|
+
"tinycloud.encryption/decrypt",
|
|
17500
|
+
"tinycloud.encryption/network.create"
|
|
17501
|
+
]
|
|
17502
|
+
}
|
|
17452
17503
|
};
|
|
17453
17504
|
}
|
|
17454
|
-
const
|
|
17505
|
+
const rawAbilities = {};
|
|
17506
|
+
const spaceResources = request.resources.filter((entry) => {
|
|
17507
|
+
if (entry.service !== ENCRYPTION_PERMISSION_SERVICE) {
|
|
17508
|
+
return true;
|
|
17509
|
+
}
|
|
17510
|
+
const existing = rawAbilities[entry.path];
|
|
17511
|
+
if (existing === void 0) {
|
|
17512
|
+
rawAbilities[entry.path] = [...entry.actions];
|
|
17513
|
+
} else {
|
|
17514
|
+
const seen = new Set(existing);
|
|
17515
|
+
for (const action of entry.actions) {
|
|
17516
|
+
if (!seen.has(action)) {
|
|
17517
|
+
existing.push(action);
|
|
17518
|
+
seen.add(action);
|
|
17519
|
+
}
|
|
17520
|
+
}
|
|
17521
|
+
}
|
|
17522
|
+
return false;
|
|
17523
|
+
});
|
|
17524
|
+
const primarySpaceName = spaceResources.find((entry) => entry.space !== "account")?.space ?? DEFAULT_MANIFEST_SPACE;
|
|
17455
17525
|
const primarySpaceId = this.resolveSpaceName(
|
|
17456
17526
|
primarySpaceName,
|
|
17457
17527
|
address,
|
|
17458
17528
|
chainId
|
|
17459
17529
|
);
|
|
17460
|
-
const bySpace = resourceCapabilitiesToSpaceAbilitiesMap(
|
|
17530
|
+
const bySpace = resourceCapabilitiesToSpaceAbilitiesMap(spaceResources);
|
|
17461
17531
|
const spaceAbilities = {};
|
|
17462
17532
|
for (const [space, abilities] of Object.entries(bySpace)) {
|
|
17463
17533
|
spaceAbilities[this.resolveSpaceName(space, address, chainId)] = abilities;
|
|
@@ -17465,7 +17535,8 @@ var NodeUserAuthorization = class {
|
|
|
17465
17535
|
return {
|
|
17466
17536
|
abilities: spaceAbilities[primarySpaceId] ?? resourceCapabilitiesToAbilitiesMap([]),
|
|
17467
17537
|
spaceId: primarySpaceId,
|
|
17468
|
-
spaceAbilities
|
|
17538
|
+
spaceAbilities,
|
|
17539
|
+
rawAbilities: Object.keys(rawAbilities).length > 0 ? rawAbilities : void 0
|
|
17469
17540
|
};
|
|
17470
17541
|
}
|
|
17471
17542
|
/**
|
|
@@ -17690,6 +17761,7 @@ var NodeUserAuthorization = class {
|
|
|
17690
17761
|
const prepared = this.wasm.prepareSession({
|
|
17691
17762
|
abilities: capabilityPlan.abilities,
|
|
17692
17763
|
...capabilityPlan.spaceAbilities !== void 0 ? { spaceAbilities: capabilityPlan.spaceAbilities } : {},
|
|
17764
|
+
...capabilityPlan.rawAbilities !== void 0 ? { rawAbilities: capabilityPlan.rawAbilities } : {},
|
|
17693
17765
|
address,
|
|
17694
17766
|
chainId,
|
|
17695
17767
|
domain: this.domain,
|
|
@@ -17835,6 +17907,7 @@ var NodeUserAuthorization = class {
|
|
|
17835
17907
|
const prepared = this.wasm.prepareSession({
|
|
17836
17908
|
abilities: capabilityPlan.abilities,
|
|
17837
17909
|
...capabilityPlan.spaceAbilities !== void 0 ? { spaceAbilities: capabilityPlan.spaceAbilities } : {},
|
|
17910
|
+
...capabilityPlan.rawAbilities !== void 0 ? { rawAbilities: capabilityPlan.rawAbilities } : {},
|
|
17838
17911
|
address,
|
|
17839
17912
|
chainId,
|
|
17840
17913
|
domain: this.domain,
|
|
@@ -18182,7 +18255,8 @@ function createWasmKeyProvider(sessionManager) {
|
|
|
18182
18255
|
// src/delegateToHelpers.ts
|
|
18183
18256
|
import {
|
|
18184
18257
|
parseExpiry,
|
|
18185
|
-
SiweMessage
|
|
18258
|
+
SiweMessage,
|
|
18259
|
+
EXPIRY as EXPIRY2
|
|
18186
18260
|
} from "@tinycloud/sdk-core";
|
|
18187
18261
|
function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
|
|
18188
18262
|
const byService = /* @__PURE__ */ new Map();
|
|
@@ -18214,9 +18288,10 @@ function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
|
|
|
18214
18288
|
}
|
|
18215
18289
|
return entries;
|
|
18216
18290
|
}
|
|
18291
|
+
var DEFAULT_DELEGATION_EXPIRY_MS = EXPIRY2.SESSION_MS;
|
|
18217
18292
|
function resolveExpiryMs(expiry) {
|
|
18218
18293
|
if (expiry === void 0) {
|
|
18219
|
-
return
|
|
18294
|
+
return DEFAULT_DELEGATION_EXPIRY_MS;
|
|
18220
18295
|
}
|
|
18221
18296
|
if (typeof expiry === "number") {
|
|
18222
18297
|
if (!Number.isFinite(expiry) || expiry <= 0) {
|
|
@@ -18245,10 +18320,11 @@ function extractSiweExpiration(siwe) {
|
|
|
18245
18320
|
// src/NodeSecretsService.ts
|
|
18246
18321
|
import {
|
|
18247
18322
|
ErrorCodes,
|
|
18323
|
+
resolveSecretListPrefix,
|
|
18324
|
+
resolveSecretPath,
|
|
18325
|
+
expandPermissionEntries,
|
|
18248
18326
|
resolveManifest
|
|
18249
18327
|
} from "@tinycloud/sdk-core";
|
|
18250
|
-
var SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
|
|
18251
|
-
var SECRET_PREFIX = "secrets/";
|
|
18252
18328
|
var SECRETS_SPACE = "secrets";
|
|
18253
18329
|
function ok() {
|
|
18254
18330
|
return { ok: true, data: void 0 };
|
|
@@ -18264,32 +18340,40 @@ function secretsError(code, message, cause) {
|
|
|
18264
18340
|
}
|
|
18265
18341
|
};
|
|
18266
18342
|
}
|
|
18267
|
-
function
|
|
18268
|
-
|
|
18343
|
+
function displayActionUrn(action) {
|
|
18344
|
+
switch (action) {
|
|
18345
|
+
case "get":
|
|
18346
|
+
return "tinycloud.kv/get";
|
|
18347
|
+
case "put":
|
|
18348
|
+
return "tinycloud.kv/put";
|
|
18349
|
+
case "del":
|
|
18350
|
+
return "tinycloud.kv/del";
|
|
18351
|
+
case "list":
|
|
18352
|
+
return "tinycloud.kv/list";
|
|
18353
|
+
}
|
|
18269
18354
|
}
|
|
18270
|
-
function
|
|
18271
|
-
return
|
|
18355
|
+
function secretActionName(action) {
|
|
18356
|
+
return action;
|
|
18272
18357
|
}
|
|
18273
|
-
function secretPermissionEntries(name, action) {
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18278
|
-
|
|
18279
|
-
|
|
18280
|
-
|
|
18281
|
-
|
|
18282
|
-
|
|
18283
|
-
|
|
18284
|
-
|
|
18285
|
-
|
|
18286
|
-
|
|
18358
|
+
function secretPermissionEntries(name, options, action, encryptionNetworkId) {
|
|
18359
|
+
const entries = [];
|
|
18360
|
+
const path = action === "list" ? resolveSecretListPrefix(options) : resolveSecretPath(name, options).permissionPaths.vault;
|
|
18361
|
+
entries.push({
|
|
18362
|
+
service: "tinycloud.kv",
|
|
18363
|
+
space: SECRETS_SPACE,
|
|
18364
|
+
path,
|
|
18365
|
+
actions: [secretActionName(action)],
|
|
18366
|
+
skipPrefix: true
|
|
18367
|
+
});
|
|
18368
|
+
if (action === "get" && encryptionNetworkId !== void 0) {
|
|
18369
|
+
entries.push({
|
|
18370
|
+
service: "tinycloud.encryption",
|
|
18371
|
+
path: encryptionNetworkId,
|
|
18372
|
+
actions: ["decrypt"],
|
|
18287
18373
|
skipPrefix: true
|
|
18288
|
-
}
|
|
18289
|
-
|
|
18290
|
-
|
|
18291
|
-
function isSecretsSpace(space) {
|
|
18292
|
-
return space === SECRETS_SPACE || space.endsWith(`:${SECRETS_SPACE}`);
|
|
18374
|
+
});
|
|
18375
|
+
}
|
|
18376
|
+
return entries;
|
|
18293
18377
|
}
|
|
18294
18378
|
var NodeSecretsService = class {
|
|
18295
18379
|
constructor(config) {
|
|
@@ -18317,48 +18401,62 @@ var NodeSecretsService = class {
|
|
|
18317
18401
|
this.shouldRestoreUnlock = false;
|
|
18318
18402
|
this.service.lock();
|
|
18319
18403
|
}
|
|
18320
|
-
get(name) {
|
|
18321
|
-
|
|
18404
|
+
async get(name, options) {
|
|
18405
|
+
const permission = await this.ensurePermission(name, options, "get");
|
|
18406
|
+
if (!permission.ok) return permission;
|
|
18407
|
+
return options === void 0 ? this.service.get(name) : this.service.get(name, options);
|
|
18322
18408
|
}
|
|
18323
|
-
async put(name, value) {
|
|
18324
|
-
const permission = await this.
|
|
18409
|
+
async put(name, value, options) {
|
|
18410
|
+
const permission = await this.ensurePermission(name, options, "put");
|
|
18325
18411
|
if (!permission.ok) return permission;
|
|
18326
|
-
return this.service.put(name, value);
|
|
18412
|
+
return options === void 0 ? this.service.put(name, value) : this.service.put(name, value, options);
|
|
18327
18413
|
}
|
|
18328
|
-
async delete(name) {
|
|
18329
|
-
const permission = await this.
|
|
18414
|
+
async delete(name, options) {
|
|
18415
|
+
const permission = await this.ensurePermission(name, options, "del");
|
|
18330
18416
|
if (!permission.ok) return permission;
|
|
18331
|
-
return this.service.delete(name);
|
|
18417
|
+
return options === void 0 ? this.service.delete(name) : this.service.delete(name, options);
|
|
18332
18418
|
}
|
|
18333
|
-
list() {
|
|
18334
|
-
|
|
18419
|
+
async list(options) {
|
|
18420
|
+
const permission = await this.ensurePermission("", options, "list");
|
|
18421
|
+
if (!permission.ok) return permission;
|
|
18422
|
+
return options === void 0 ? this.service.list() : this.service.list(options);
|
|
18335
18423
|
}
|
|
18336
18424
|
get service() {
|
|
18337
18425
|
return this.config.getService();
|
|
18338
18426
|
}
|
|
18339
|
-
async
|
|
18340
|
-
|
|
18427
|
+
async ensurePermission(name, options, action) {
|
|
18428
|
+
const target = name || "secrets";
|
|
18429
|
+
let permissionEntries;
|
|
18430
|
+
try {
|
|
18431
|
+
permissionEntries = secretPermissionEntries(
|
|
18432
|
+
name,
|
|
18433
|
+
options,
|
|
18434
|
+
action,
|
|
18435
|
+
action === "get" ? this.config.getEncryptionNetworkId?.() : void 0
|
|
18436
|
+
);
|
|
18437
|
+
} catch (error) {
|
|
18341
18438
|
return secretsError(
|
|
18342
18439
|
ErrorCodes.INVALID_INPUT,
|
|
18343
|
-
|
|
18440
|
+
error instanceof Error ? error.message : String(error),
|
|
18441
|
+
error instanceof Error ? error : void 0
|
|
18344
18442
|
);
|
|
18345
18443
|
}
|
|
18346
|
-
if (this.
|
|
18444
|
+
if (this.hasPermission(permissionEntries)) {
|
|
18347
18445
|
return ok();
|
|
18348
18446
|
}
|
|
18349
18447
|
if (!this.config.canEscalate()) {
|
|
18350
18448
|
return secretsError(
|
|
18351
18449
|
ErrorCodes.PERMISSION_DENIED,
|
|
18352
|
-
`Cannot autosign ${
|
|
18450
|
+
`Cannot autosign ${displayActionUrn(action)} for ${target}; TinyCloudNode needs wallet mode with a signer or privateKey.`
|
|
18353
18451
|
);
|
|
18354
18452
|
}
|
|
18355
18453
|
try {
|
|
18356
|
-
await this.config.grantPermissions(
|
|
18454
|
+
await this.config.grantPermissions(permissionEntries);
|
|
18357
18455
|
return this.restoreUnlockAfterEscalation();
|
|
18358
18456
|
} catch (error) {
|
|
18359
18457
|
return secretsError(
|
|
18360
18458
|
ErrorCodes.PERMISSION_DENIED,
|
|
18361
|
-
error instanceof Error ? error.message : `Autosign escalation for ${
|
|
18459
|
+
error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${target} failed.`,
|
|
18362
18460
|
error instanceof Error ? error : void 0
|
|
18363
18461
|
);
|
|
18364
18462
|
}
|
|
@@ -18369,26 +18467,117 @@ var NodeSecretsService = class {
|
|
|
18369
18467
|
}
|
|
18370
18468
|
return this.service.unlock(this.unlockSigner);
|
|
18371
18469
|
}
|
|
18372
|
-
|
|
18470
|
+
hasPermission(permissionEntries) {
|
|
18471
|
+
if (this.config.hasPermissions?.(permissionEntries)) {
|
|
18472
|
+
return true;
|
|
18473
|
+
}
|
|
18373
18474
|
const manifest = this.config.getManifest();
|
|
18374
18475
|
if (manifest === void 0) {
|
|
18375
18476
|
return false;
|
|
18376
18477
|
}
|
|
18377
18478
|
const manifests = Array.isArray(manifest) ? manifest : [manifest];
|
|
18378
|
-
const
|
|
18379
|
-
return
|
|
18380
|
-
|
|
18381
|
-
|
|
18382
|
-
|
|
18383
|
-
(resource) => resource.service ===
|
|
18384
|
-
)
|
|
18385
|
-
)
|
|
18386
|
-
|
|
18479
|
+
const requestedEntries = expandPermissionEntries(permissionEntries);
|
|
18480
|
+
return requestedEntries.every(
|
|
18481
|
+
(entry) => manifests.some((candidate) => {
|
|
18482
|
+
const resolved = resolveManifest(candidate);
|
|
18483
|
+
return resolved.resources.some(
|
|
18484
|
+
(resource) => resource.service === entry.service && resource.space === entry.space && resource.path === entry.path && entry.actions.every((action) => resource.actions.includes(action))
|
|
18485
|
+
);
|
|
18486
|
+
})
|
|
18487
|
+
);
|
|
18387
18488
|
}
|
|
18388
18489
|
};
|
|
18389
18490
|
|
|
18390
18491
|
// src/TinyCloudNode.ts
|
|
18391
18492
|
var DEFAULT_HOST = "https://node.tinycloud.xyz";
|
|
18493
|
+
var DEFAULT_ENCRYPTION_NETWORK_NAME = "default";
|
|
18494
|
+
var NETWORK_CREATE_ACTION = "tinycloud.encryption/network.create";
|
|
18495
|
+
var DECRYPT_ACTION = "tinycloud.encryption/decrypt";
|
|
18496
|
+
var NETWORK_ADMIN_TYPE = "tinycloud.encryption.network-admin/v1";
|
|
18497
|
+
var DEFAULT_SESSION_EXPIRATION_MS = EXPIRY3.SESSION_MS;
|
|
18498
|
+
function base64UrlEncode(bytes) {
|
|
18499
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
18500
|
+
let output = "";
|
|
18501
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
18502
|
+
const a = bytes[i];
|
|
18503
|
+
const b = bytes[i + 1];
|
|
18504
|
+
const c = bytes[i + 2];
|
|
18505
|
+
const triplet = a << 16 | (b ?? 0) << 8 | (c ?? 0);
|
|
18506
|
+
output += alphabet[triplet >> 18 & 63];
|
|
18507
|
+
output += alphabet[triplet >> 12 & 63];
|
|
18508
|
+
if (i + 1 < bytes.length) output += alphabet[triplet >> 6 & 63];
|
|
18509
|
+
if (i + 2 < bytes.length) output += alphabet[triplet & 63];
|
|
18510
|
+
}
|
|
18511
|
+
return output;
|
|
18512
|
+
}
|
|
18513
|
+
function base64UrlDecode(value) {
|
|
18514
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
18515
|
+
const bytes = [];
|
|
18516
|
+
let buffer = 0;
|
|
18517
|
+
let bits = 0;
|
|
18518
|
+
for (const char of value) {
|
|
18519
|
+
const index = alphabet.indexOf(char);
|
|
18520
|
+
if (index < 0) {
|
|
18521
|
+
throw new Error("invalid base64url input");
|
|
18522
|
+
}
|
|
18523
|
+
buffer = buffer << 6 | index;
|
|
18524
|
+
bits += 6;
|
|
18525
|
+
if (bits >= 8) {
|
|
18526
|
+
bits -= 8;
|
|
18527
|
+
bytes.push(buffer >> bits & 255);
|
|
18528
|
+
}
|
|
18529
|
+
}
|
|
18530
|
+
return new Uint8Array(bytes);
|
|
18531
|
+
}
|
|
18532
|
+
async function signJwtInputWithJwk(signingInput, jwk) {
|
|
18533
|
+
const bytes = new TextEncoder().encode(signingInput);
|
|
18534
|
+
try {
|
|
18535
|
+
const subtle = globalThis.crypto?.subtle;
|
|
18536
|
+
if (!subtle) {
|
|
18537
|
+
throw new Error("WebCrypto subtle API is unavailable");
|
|
18538
|
+
}
|
|
18539
|
+
const key2 = await subtle.importKey(
|
|
18540
|
+
"jwk",
|
|
18541
|
+
jwk,
|
|
18542
|
+
{ name: "Ed25519" },
|
|
18543
|
+
false,
|
|
18544
|
+
["sign"]
|
|
18545
|
+
);
|
|
18546
|
+
return new Uint8Array(await subtle.sign({ name: "Ed25519" }, key2, bytes));
|
|
18547
|
+
} catch {
|
|
18548
|
+
const nodeCrypto = await import("crypto");
|
|
18549
|
+
const key2 = nodeCrypto.createPrivateKey({ key: jwk, format: "jwk" });
|
|
18550
|
+
return new Uint8Array(nodeCrypto.sign(null, Buffer.from(bytes), key2));
|
|
18551
|
+
}
|
|
18552
|
+
}
|
|
18553
|
+
async function rewriteInvocationAudience(authorization, audience, jwk) {
|
|
18554
|
+
const [headerPart, payloadPart] = authorization.split(".");
|
|
18555
|
+
if (!headerPart || !payloadPart) {
|
|
18556
|
+
throw new Error("invalid invocation authorization");
|
|
18557
|
+
}
|
|
18558
|
+
const header = JSON.parse(new TextDecoder().decode(base64UrlDecode(headerPart)));
|
|
18559
|
+
const payload = JSON.parse(new TextDecoder().decode(base64UrlDecode(payloadPart)));
|
|
18560
|
+
payload.aud = audience;
|
|
18561
|
+
const signingInput = `${base64UrlEncode(
|
|
18562
|
+
new TextEncoder().encode(JSON.stringify(header))
|
|
18563
|
+
)}.${base64UrlEncode(new TextEncoder().encode(JSON.stringify(payload)))}`;
|
|
18564
|
+
const signature2 = await signJwtInputWithJwk(signingInput, jwk);
|
|
18565
|
+
return `${signingInput}.${base64UrlEncode(signature2)}`;
|
|
18566
|
+
}
|
|
18567
|
+
function authorizationHeader(headers) {
|
|
18568
|
+
if (Array.isArray(headers)) {
|
|
18569
|
+
const entry = headers.find(([name]) => name.toLowerCase() === "authorization");
|
|
18570
|
+
if (!entry) {
|
|
18571
|
+
throw new Error("network invocation did not include an Authorization header");
|
|
18572
|
+
}
|
|
18573
|
+
return entry[1];
|
|
18574
|
+
}
|
|
18575
|
+
const value = headers.Authorization ?? headers.authorization;
|
|
18576
|
+
if (!value) {
|
|
18577
|
+
throw new Error("network invocation did not include an Authorization header");
|
|
18578
|
+
}
|
|
18579
|
+
return value;
|
|
18580
|
+
}
|
|
18392
18581
|
var _TinyCloudNode = class _TinyCloudNode {
|
|
18393
18582
|
/**
|
|
18394
18583
|
* Create a new TinyCloudNode instance.
|
|
@@ -18433,12 +18622,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18433
18622
|
throw new Error("WASM binding does not support invokeAny");
|
|
18434
18623
|
}
|
|
18435
18624
|
const grant = this.findGrantForOperations(
|
|
18436
|
-
entries.
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18440
|
-
action: entry.action
|
|
18441
|
-
}))
|
|
18625
|
+
entries.flatMap((entry) => {
|
|
18626
|
+
const operation = this.operationFromInvokeAnyEntry(entry);
|
|
18627
|
+
return operation ? [operation] : [];
|
|
18628
|
+
})
|
|
18442
18629
|
);
|
|
18443
18630
|
return this.wasmBindings.invokeAny(grant?.session ?? session, entries, facts);
|
|
18444
18631
|
};
|
|
@@ -18531,7 +18718,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18531
18718
|
sessionStorage: config.sessionStorage ?? new MemorySessionStorage(),
|
|
18532
18719
|
domain: this.siweDomain,
|
|
18533
18720
|
spacePrefix: config.prefix,
|
|
18534
|
-
sessionExpirationMs: config.sessionExpirationMs ??
|
|
18721
|
+
sessionExpirationMs: config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
|
|
18535
18722
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
18536
18723
|
tinycloudRegistryUrl: config.tinycloudRegistryUrl,
|
|
18537
18724
|
tinycloudFallbackHosts: config.tinycloudFallbackHosts,
|
|
@@ -18666,6 +18853,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18666
18853
|
this._duckdb = void 0;
|
|
18667
18854
|
this._hooks = void 0;
|
|
18668
18855
|
this._vault = void 0;
|
|
18856
|
+
this._encryption = void 0;
|
|
18669
18857
|
this._baseSecrets = void 0;
|
|
18670
18858
|
this._secrets = void 0;
|
|
18671
18859
|
this._spaceService = void 0;
|
|
@@ -18674,6 +18862,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18674
18862
|
await this.tc.signIn(options);
|
|
18675
18863
|
this.syncResolvedHostFromAuth();
|
|
18676
18864
|
this.initializeServices();
|
|
18865
|
+
if (this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
|
|
18866
|
+
await this.ensureOwnedSpaceHosted(this.ownedSpaceId("secrets"));
|
|
18867
|
+
}
|
|
18677
18868
|
await this.writeManifestRegistryRecords();
|
|
18678
18869
|
this.notificationHandler.success("Successfully signed in");
|
|
18679
18870
|
}
|
|
@@ -18756,6 +18947,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18756
18947
|
this._duckdb = void 0;
|
|
18757
18948
|
this._hooks = void 0;
|
|
18758
18949
|
this._vault = void 0;
|
|
18950
|
+
this._encryption = void 0;
|
|
18759
18951
|
this._baseSecrets = void 0;
|
|
18760
18952
|
this._secrets = void 0;
|
|
18761
18953
|
this._spaceService = void 0;
|
|
@@ -18797,6 +18989,33 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18797
18989
|
this._vault.initialize(this._serviceContext);
|
|
18798
18990
|
this._serviceContext.registerService("vault", this._vault);
|
|
18799
18991
|
this.initializeV2Services(serviceSession);
|
|
18992
|
+
if (sessionData.siwe && sessionData.address && sessionData.chainId) {
|
|
18993
|
+
const tcSession = {
|
|
18994
|
+
address: sessionData.address,
|
|
18995
|
+
chainId: sessionData.chainId,
|
|
18996
|
+
sessionKey: JSON.stringify(sessionData.jwk),
|
|
18997
|
+
spaceId: sessionData.spaceId,
|
|
18998
|
+
delegationCid: sessionData.delegationCid,
|
|
18999
|
+
delegationHeader: sessionData.delegationHeader,
|
|
19000
|
+
verificationMethod: sessionData.verificationMethod,
|
|
19001
|
+
jwk: sessionData.jwk,
|
|
19002
|
+
siwe: sessionData.siwe,
|
|
19003
|
+
signature: sessionData.signature ?? ""
|
|
19004
|
+
};
|
|
19005
|
+
if (this.auth) {
|
|
19006
|
+
this.auth.setRestoredTinyCloudSession(tcSession);
|
|
19007
|
+
} else {
|
|
19008
|
+
this._restoredTcSession = tcSession;
|
|
19009
|
+
}
|
|
19010
|
+
}
|
|
19011
|
+
}
|
|
19012
|
+
/**
|
|
19013
|
+
* Resolve the currently-active TinyCloudSession, preferring the auth
|
|
19014
|
+
* layer's value (wallet mode) and falling back to the node-level
|
|
19015
|
+
* rehydration set by {@link restoreSession} (session-only mode).
|
|
19016
|
+
*/
|
|
19017
|
+
currentTinyCloudSession() {
|
|
19018
|
+
return this.auth?.tinyCloudSession ?? this._restoredTcSession;
|
|
18800
19019
|
}
|
|
18801
19020
|
/**
|
|
18802
19021
|
* Connect a wallet to upgrade from session-only mode to wallet mode.
|
|
@@ -18841,7 +19060,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18841
19060
|
sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
|
|
18842
19061
|
domain: this.siweDomain,
|
|
18843
19062
|
spacePrefix: prefix,
|
|
18844
|
-
sessionExpirationMs: this.config.sessionExpirationMs ??
|
|
19063
|
+
sessionExpirationMs: this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
|
|
18845
19064
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
18846
19065
|
tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
|
|
18847
19066
|
tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
|
|
@@ -18885,7 +19104,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18885
19104
|
sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
|
|
18886
19105
|
domain: this.siweDomain,
|
|
18887
19106
|
spacePrefix: prefix,
|
|
18888
|
-
sessionExpirationMs: this.config.sessionExpirationMs ??
|
|
19107
|
+
sessionExpirationMs: this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
|
|
18889
19108
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
18890
19109
|
tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
|
|
18891
19110
|
tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
|
|
@@ -18908,7 +19127,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18908
19127
|
* @internal
|
|
18909
19128
|
*/
|
|
18910
19129
|
initializeServices() {
|
|
18911
|
-
const session = this.
|
|
19130
|
+
const session = this.currentTinyCloudSession();
|
|
18912
19131
|
if (!session) {
|
|
18913
19132
|
return;
|
|
18914
19133
|
}
|
|
@@ -18966,6 +19185,163 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18966
19185
|
}
|
|
18967
19186
|
return kvService;
|
|
18968
19187
|
}
|
|
19188
|
+
getDefaultEncryptionNetworkId(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
19189
|
+
return `urn:tinycloud:encryption:${this.did}:${name}`;
|
|
19190
|
+
}
|
|
19191
|
+
requireServiceSession() {
|
|
19192
|
+
const session = this._serviceContext?.session;
|
|
19193
|
+
if (!session) {
|
|
19194
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
19195
|
+
}
|
|
19196
|
+
return session;
|
|
19197
|
+
}
|
|
19198
|
+
createEncryptionCrypto() {
|
|
19199
|
+
const wasm = this.wasmBindings;
|
|
19200
|
+
const columnEncrypt = (key2, plaintext) => {
|
|
19201
|
+
const encrypted = wasm.vault_encrypt(key2, plaintext);
|
|
19202
|
+
const out = new Uint8Array(1 + encrypted.length);
|
|
19203
|
+
out[0] = 1;
|
|
19204
|
+
out.set(encrypted, 1);
|
|
19205
|
+
return out;
|
|
19206
|
+
};
|
|
19207
|
+
const columnDecrypt = (key2, blob) => {
|
|
19208
|
+
if (blob[0] !== 1) {
|
|
19209
|
+
return blob;
|
|
19210
|
+
}
|
|
19211
|
+
return wasm.vault_decrypt(key2, blob.slice(1));
|
|
19212
|
+
};
|
|
19213
|
+
return {
|
|
19214
|
+
sha256: (data) => wasm.vault_sha256(data),
|
|
19215
|
+
randomBytes: (length) => wasm.vault_random_bytes(length),
|
|
19216
|
+
x25519FromSeed: (seed) => wasm.vault_x25519_from_seed(seed),
|
|
19217
|
+
x25519Dh: (privateKey, publicKey) => wasm.vault_x25519_dh(privateKey, publicKey),
|
|
19218
|
+
authEncrypt: (key2, plaintext) => wasm.vault_encrypt(key2, plaintext),
|
|
19219
|
+
authDecrypt: (key2, ciphertext) => wasm.vault_decrypt(key2, ciphertext),
|
|
19220
|
+
sealToNetworkKey: (networkPublicKey, symmetricKey) => {
|
|
19221
|
+
const seed = wasm.vault_random_bytes(32);
|
|
19222
|
+
const ephemeral = wasm.vault_x25519_from_seed(seed);
|
|
19223
|
+
const shared = wasm.vault_x25519_dh(
|
|
19224
|
+
ephemeral.privateKey,
|
|
19225
|
+
networkPublicKey
|
|
19226
|
+
);
|
|
19227
|
+
const encrypted = columnEncrypt(shared, symmetricKey);
|
|
19228
|
+
const out = new Uint8Array(ephemeral.publicKey.length + encrypted.length);
|
|
19229
|
+
out.set(ephemeral.publicKey, 0);
|
|
19230
|
+
out.set(encrypted, ephemeral.publicKey.length);
|
|
19231
|
+
return out;
|
|
19232
|
+
},
|
|
19233
|
+
openWithReceiverKey: (receiverPrivateKey, wrappedKey) => {
|
|
19234
|
+
const peerPublic = wrappedKey.slice(0, 32);
|
|
19235
|
+
const ciphertext = wrappedKey.slice(32);
|
|
19236
|
+
const shared = wasm.vault_x25519_dh(receiverPrivateKey, peerPublic);
|
|
19237
|
+
return columnDecrypt(shared, ciphertext);
|
|
19238
|
+
},
|
|
19239
|
+
verifyNodeSignature: (nodeId, message, signature2) => verifyDidKeyEd25519Signature(nodeId, message, signature2)
|
|
19240
|
+
};
|
|
19241
|
+
}
|
|
19242
|
+
async fetchNodeId() {
|
|
19243
|
+
const response = await fetch(`${this.config.host}/info`);
|
|
19244
|
+
if (!response.ok) {
|
|
19245
|
+
throw new Error(`Failed to fetch node info: HTTP ${response.status}`);
|
|
19246
|
+
}
|
|
19247
|
+
const info = await response.json();
|
|
19248
|
+
if (typeof info.nodeId !== "string" || info.nodeId.length === 0) {
|
|
19249
|
+
throw new Error("Node /info response did not include nodeId");
|
|
19250
|
+
}
|
|
19251
|
+
return info.nodeId;
|
|
19252
|
+
}
|
|
19253
|
+
async signRawNetworkAuthorization(input) {
|
|
19254
|
+
if (!this.wasmBindings.invokeAny) {
|
|
19255
|
+
throw new Error("WASM binding does not support raw-resource invokeAny");
|
|
19256
|
+
}
|
|
19257
|
+
if (!this.wasmBindings.computeCid) {
|
|
19258
|
+
throw new Error("WASM binding does not support invocation CID computation");
|
|
19259
|
+
}
|
|
19260
|
+
const session = this.requireServiceSession();
|
|
19261
|
+
const headers = this.invokeAnyWithRuntimePermissions(
|
|
19262
|
+
session,
|
|
19263
|
+
[
|
|
19264
|
+
{
|
|
19265
|
+
resource: input.networkId,
|
|
19266
|
+
service: "encryption",
|
|
19267
|
+
path: input.networkId,
|
|
19268
|
+
action: input.action
|
|
19269
|
+
}
|
|
19270
|
+
],
|
|
19271
|
+
[input.facts]
|
|
19272
|
+
);
|
|
19273
|
+
const authorization = authorizationHeader(headers);
|
|
19274
|
+
const audienceBound = await rewriteInvocationAudience(
|
|
19275
|
+
authorization,
|
|
19276
|
+
input.targetNode,
|
|
19277
|
+
session.jwk
|
|
19278
|
+
);
|
|
19279
|
+
return {
|
|
19280
|
+
authorization: audienceBound,
|
|
19281
|
+
invocationCid: this.wasmBindings.computeCid(
|
|
19282
|
+
new TextEncoder().encode(audienceBound),
|
|
19283
|
+
0x55n
|
|
19284
|
+
)
|
|
19285
|
+
};
|
|
19286
|
+
}
|
|
19287
|
+
createEncryptionService() {
|
|
19288
|
+
const crypto2 = this.createEncryptionCrypto();
|
|
19289
|
+
const transport = {
|
|
19290
|
+
postDecrypt: async ({ networkId, authorization, canonicalBody }) => {
|
|
19291
|
+
const response = await fetch(
|
|
19292
|
+
`${this.config.host}/encryption/networks/${encodeURIComponent(networkId)}/decrypt`,
|
|
19293
|
+
{
|
|
19294
|
+
method: "POST",
|
|
19295
|
+
headers: {
|
|
19296
|
+
Authorization: authorization,
|
|
19297
|
+
"Content-Type": "application/json"
|
|
19298
|
+
},
|
|
19299
|
+
body: canonicalBody
|
|
19300
|
+
}
|
|
19301
|
+
);
|
|
19302
|
+
if (!response.ok) {
|
|
19303
|
+
throw new Error(
|
|
19304
|
+
`decrypt failed ${response.status}: ${await response.text()}`
|
|
19305
|
+
);
|
|
19306
|
+
}
|
|
19307
|
+
return await response.json();
|
|
19308
|
+
}
|
|
19309
|
+
};
|
|
19310
|
+
return new EncryptionService({
|
|
19311
|
+
crypto: crypto2,
|
|
19312
|
+
signer: {
|
|
19313
|
+
signDecryptInvocation: async (input) => {
|
|
19314
|
+
const signed2 = await this.signRawNetworkAuthorization({
|
|
19315
|
+
targetNode: input.targetNode,
|
|
19316
|
+
networkId: input.networkId,
|
|
19317
|
+
action: DECRYPT_ACTION,
|
|
19318
|
+
facts: input.facts
|
|
19319
|
+
});
|
|
19320
|
+
return {
|
|
19321
|
+
...signed2,
|
|
19322
|
+
canonicalBody: canonicalizeEncryptionJson(
|
|
19323
|
+
input.body
|
|
19324
|
+
)
|
|
19325
|
+
};
|
|
19326
|
+
}
|
|
19327
|
+
},
|
|
19328
|
+
transport,
|
|
19329
|
+
node: {
|
|
19330
|
+
fetchByNetworkId: (networkId) => this.getEncryptionNetwork(networkId)
|
|
19331
|
+
}
|
|
19332
|
+
});
|
|
19333
|
+
}
|
|
19334
|
+
getEncryptionService() {
|
|
19335
|
+
if (!this._serviceContext) {
|
|
19336
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
19337
|
+
}
|
|
19338
|
+
if (!this._encryption) {
|
|
19339
|
+
this._encryption = this.createEncryptionService();
|
|
19340
|
+
this._encryption.initialize(this._serviceContext);
|
|
19341
|
+
this._serviceContext.registerService("encryption", this._encryption);
|
|
19342
|
+
}
|
|
19343
|
+
return this._encryption;
|
|
19344
|
+
}
|
|
18969
19345
|
createVaultService(spaceId, kv) {
|
|
18970
19346
|
const wasm = this.wasmBindings;
|
|
18971
19347
|
const vaultCrypto = createVaultCrypto({
|
|
@@ -18981,6 +19357,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18981
19357
|
return new DataVaultService({
|
|
18982
19358
|
spaceId,
|
|
18983
19359
|
crypto: vaultCrypto,
|
|
19360
|
+
encryption: {
|
|
19361
|
+
networkId: this.getDefaultEncryptionNetworkId(),
|
|
19362
|
+
service: this.getEncryptionService(),
|
|
19363
|
+
decryptCapabilityProof: () => ({
|
|
19364
|
+
proofs: [this.requireServiceSession().delegationCid]
|
|
19365
|
+
})
|
|
19366
|
+
},
|
|
18984
19367
|
tc: {
|
|
18985
19368
|
kv,
|
|
18986
19369
|
ensurePublicSpace: async () => {
|
|
@@ -19161,7 +19544,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19161
19544
|
* @internal
|
|
19162
19545
|
*/
|
|
19163
19546
|
getSessionExpiry() {
|
|
19164
|
-
const expirationMs = this.config.sessionExpirationMs ??
|
|
19547
|
+
const expirationMs = this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS;
|
|
19165
19548
|
return new Date(Date.now() + expirationMs);
|
|
19166
19549
|
}
|
|
19167
19550
|
/**
|
|
@@ -19218,7 +19601,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19218
19601
|
if (!this.signer) {
|
|
19219
19602
|
return void 0;
|
|
19220
19603
|
}
|
|
19221
|
-
const session = this.
|
|
19604
|
+
const session = this.currentTinyCloudSession();
|
|
19222
19605
|
if (!session) {
|
|
19223
19606
|
return void 0;
|
|
19224
19607
|
}
|
|
@@ -19318,6 +19701,34 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19318
19701
|
}
|
|
19319
19702
|
return this._sql;
|
|
19320
19703
|
}
|
|
19704
|
+
/**
|
|
19705
|
+
* Get an SQL service scoped to a specific space.
|
|
19706
|
+
*
|
|
19707
|
+
* Mirrors {@link SpaceService}'s per-space KV factory: clones the active
|
|
19708
|
+
* service context and overrides its session's spaceId so that subsequent
|
|
19709
|
+
* `sql/<dbName>/<action>` invocations route to that space. Useful when
|
|
19710
|
+
* the caller already holds a delegation covering the target space (e.g.
|
|
19711
|
+
* via {@link grantRuntimePermissions} or {@link useRuntimeDelegation})
|
|
19712
|
+
* but the SDK's per-space SQL surface isn't otherwise exposed.
|
|
19713
|
+
*
|
|
19714
|
+
* Does NOT auto-create the space.
|
|
19715
|
+
*
|
|
19716
|
+
* @param spaceId - Full space URI (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`).
|
|
19717
|
+
*/
|
|
19718
|
+
sqlForSpace(spaceId) {
|
|
19719
|
+
if (!this._serviceContext || !this._serviceContext.session) {
|
|
19720
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
19721
|
+
}
|
|
19722
|
+
const sql = new SQLService2({});
|
|
19723
|
+
const spaceScopedContext = new ServiceContext2({
|
|
19724
|
+
invoke: this._serviceContext.invoke,
|
|
19725
|
+
fetch: this._serviceContext.fetch,
|
|
19726
|
+
hosts: this._serviceContext.hosts
|
|
19727
|
+
});
|
|
19728
|
+
spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
|
|
19729
|
+
sql.initialize(spaceScopedContext);
|
|
19730
|
+
return sql;
|
|
19731
|
+
}
|
|
19321
19732
|
/**
|
|
19322
19733
|
* DuckDB database operations on this user's space.
|
|
19323
19734
|
*/
|
|
@@ -19341,6 +19752,79 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19341
19752
|
}
|
|
19342
19753
|
return this._vault;
|
|
19343
19754
|
}
|
|
19755
|
+
/**
|
|
19756
|
+
* Network-scoped encryption/decrypt service.
|
|
19757
|
+
*/
|
|
19758
|
+
get encryption() {
|
|
19759
|
+
return this.getEncryptionService();
|
|
19760
|
+
}
|
|
19761
|
+
async getEncryptionNetwork(nameOrNetworkId = this.getDefaultEncryptionNetworkId()) {
|
|
19762
|
+
const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
|
|
19763
|
+
const response = await fetch(
|
|
19764
|
+
`${this.config.host}/encryption/networks/${encodeURIComponent(networkId)}`
|
|
19765
|
+
);
|
|
19766
|
+
if (response.status === 404) {
|
|
19767
|
+
return null;
|
|
19768
|
+
}
|
|
19769
|
+
if (!response.ok) {
|
|
19770
|
+
throw new Error(
|
|
19771
|
+
`Failed to fetch encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
|
|
19772
|
+
);
|
|
19773
|
+
}
|
|
19774
|
+
const body = await response.json();
|
|
19775
|
+
return "descriptor" in body && body.descriptor ? body.descriptor : body;
|
|
19776
|
+
}
|
|
19777
|
+
async createEncryptionNetwork(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
19778
|
+
const targetNode = await this.fetchNodeId();
|
|
19779
|
+
const principal = this.did;
|
|
19780
|
+
const networkId = this.getDefaultEncryptionNetworkId(name);
|
|
19781
|
+
const body = {
|
|
19782
|
+
name,
|
|
19783
|
+
principal,
|
|
19784
|
+
threshold: { n: 1, t: 1 }
|
|
19785
|
+
};
|
|
19786
|
+
const crypto2 = this.createEncryptionCrypto();
|
|
19787
|
+
const facts = {
|
|
19788
|
+
type: NETWORK_ADMIN_TYPE,
|
|
19789
|
+
targetNode,
|
|
19790
|
+
networkId,
|
|
19791
|
+
bodyHash: canonicalHashHex(
|
|
19792
|
+
crypto2.sha256,
|
|
19793
|
+
body
|
|
19794
|
+
),
|
|
19795
|
+
action: NETWORK_CREATE_ACTION
|
|
19796
|
+
};
|
|
19797
|
+
const signed2 = await this.signRawNetworkAuthorization({
|
|
19798
|
+
targetNode,
|
|
19799
|
+
networkId,
|
|
19800
|
+
action: NETWORK_CREATE_ACTION,
|
|
19801
|
+
facts
|
|
19802
|
+
});
|
|
19803
|
+
const response = await fetch(`${this.config.host}/encryption/networks`, {
|
|
19804
|
+
method: "POST",
|
|
19805
|
+
headers: {
|
|
19806
|
+
Authorization: signed2.authorization,
|
|
19807
|
+
"Content-Type": "application/json"
|
|
19808
|
+
},
|
|
19809
|
+
body: canonicalizeEncryptionJson(
|
|
19810
|
+
body
|
|
19811
|
+
)
|
|
19812
|
+
});
|
|
19813
|
+
if (!response.ok) {
|
|
19814
|
+
throw new Error(
|
|
19815
|
+
`Failed to create encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
|
|
19816
|
+
);
|
|
19817
|
+
}
|
|
19818
|
+
const created = await response.json();
|
|
19819
|
+
return created.descriptor;
|
|
19820
|
+
}
|
|
19821
|
+
async ensureEncryptionNetwork(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
19822
|
+
const existing = await this.getEncryptionNetwork(name);
|
|
19823
|
+
if (existing) {
|
|
19824
|
+
return existing;
|
|
19825
|
+
}
|
|
19826
|
+
return this.createEncryptionNetwork(name);
|
|
19827
|
+
}
|
|
19344
19828
|
/**
|
|
19345
19829
|
* App-facing secrets API backed by the `secrets` space vault.
|
|
19346
19830
|
*/
|
|
@@ -19352,8 +19836,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19352
19836
|
this._secrets = new NodeSecretsService({
|
|
19353
19837
|
getService: () => this.getBaseSecrets(),
|
|
19354
19838
|
getManifest: () => this.manifest,
|
|
19839
|
+
hasPermissions: (permissions) => this.hasRuntimePermissions(permissions),
|
|
19355
19840
|
grantPermissions: (additional) => this.grantRuntimePermissions(additional),
|
|
19356
19841
|
canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
|
|
19842
|
+
getEncryptionNetworkId: () => this.getDefaultEncryptionNetworkId(),
|
|
19357
19843
|
getUnlockSigner: () => this.signer ?? void 0
|
|
19358
19844
|
});
|
|
19359
19845
|
}
|
|
@@ -19443,7 +19929,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19443
19929
|
* every requested permission.
|
|
19444
19930
|
*/
|
|
19445
19931
|
hasRuntimePermissions(permissions) {
|
|
19446
|
-
const session = this.
|
|
19932
|
+
const session = this.currentTinyCloudSession();
|
|
19447
19933
|
if (!session || !Array.isArray(permissions) || permissions.length === 0) {
|
|
19448
19934
|
return false;
|
|
19449
19935
|
}
|
|
@@ -19463,7 +19949,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19463
19949
|
if (permissions === void 0) {
|
|
19464
19950
|
return this.runtimePermissionGrants.map((grant) => grant.delegation);
|
|
19465
19951
|
}
|
|
19466
|
-
const session = this.
|
|
19952
|
+
const session = this.currentTinyCloudSession();
|
|
19467
19953
|
if (!session || !Array.isArray(permissions) || permissions.length === 0) {
|
|
19468
19954
|
return [];
|
|
19469
19955
|
}
|
|
@@ -19477,7 +19963,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19477
19963
|
* matching service calls and downstream `delegateTo()` calls can use it.
|
|
19478
19964
|
*/
|
|
19479
19965
|
async useRuntimeDelegation(delegation) {
|
|
19480
|
-
const session = this.
|
|
19966
|
+
const session = this.currentTinyCloudSession();
|
|
19481
19967
|
if (!session) {
|
|
19482
19968
|
throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
|
|
19483
19969
|
}
|
|
@@ -19516,7 +20002,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19516
20002
|
if (!Array.isArray(permissions) || permissions.length === 0) {
|
|
19517
20003
|
throw new Error("grantRuntimePermissions requires a non-empty permissions array");
|
|
19518
20004
|
}
|
|
19519
|
-
const session = this.
|
|
20005
|
+
const session = this.currentTinyCloudSession();
|
|
19520
20006
|
if (!session) {
|
|
19521
20007
|
throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
|
|
19522
20008
|
}
|
|
@@ -19540,13 +20026,22 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19540
20026
|
"grantRuntimePermissions requires wallet mode with a signer or privateKey."
|
|
19541
20027
|
);
|
|
19542
20028
|
}
|
|
20029
|
+
const rawEntries = expanded.filter(
|
|
20030
|
+
(entry) => this.isEncryptionPermissionEntry(entry)
|
|
20031
|
+
);
|
|
20032
|
+
const spaceEntries = expanded.filter(
|
|
20033
|
+
(entry) => !this.isEncryptionPermissionEntry(entry)
|
|
20034
|
+
);
|
|
19543
20035
|
const bySpace = /* @__PURE__ */ new Map();
|
|
19544
|
-
for (const entry of
|
|
20036
|
+
for (const entry of spaceEntries) {
|
|
19545
20037
|
const spaceId = this.resolvePermissionSpace(entry.space, session);
|
|
19546
20038
|
const current = bySpace.get(spaceId) ?? [];
|
|
19547
20039
|
current.push(entry);
|
|
19548
20040
|
bySpace.set(spaceId, current);
|
|
19549
20041
|
}
|
|
20042
|
+
if (bySpace.size === 0 && rawEntries.length > 0) {
|
|
20043
|
+
bySpace.set(session.spaceId, []);
|
|
20044
|
+
}
|
|
19550
20045
|
const now = /* @__PURE__ */ new Date();
|
|
19551
20046
|
const requestedExpiryMs = resolveExpiryMs(options?.expiry);
|
|
19552
20047
|
let expiresAt = new Date(now.getTime() + requestedExpiryMs);
|
|
@@ -19554,10 +20049,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19554
20049
|
expiresAt = sessionExpiry;
|
|
19555
20050
|
}
|
|
19556
20051
|
const delegations = [];
|
|
20052
|
+
let rawEntriesAttached = false;
|
|
19557
20053
|
for (const [spaceId, entries] of bySpace) {
|
|
20054
|
+
const rawForDelegation = !rawEntriesAttached ? rawEntries : [];
|
|
20055
|
+
if (rawForDelegation.length > 0) {
|
|
20056
|
+
rawEntriesAttached = true;
|
|
20057
|
+
}
|
|
20058
|
+
const delegatedEntries = [...entries, ...rawForDelegation];
|
|
19558
20059
|
const abilities = this.permissionsToAbilities(entries);
|
|
19559
20060
|
const prepared = this.wasmBindings.prepareSession({
|
|
19560
20061
|
abilities,
|
|
20062
|
+
...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
|
|
19561
20063
|
address: this.wasmBindings.ensureEip55(session.address),
|
|
19562
20064
|
chainId: session.chainId,
|
|
19563
20065
|
domain: this.siweDomain,
|
|
@@ -19582,7 +20084,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19582
20084
|
}
|
|
19583
20085
|
const delegation = this.runtimeDelegationFromSession(
|
|
19584
20086
|
delegatedSession,
|
|
19585
|
-
|
|
20087
|
+
delegatedEntries,
|
|
19586
20088
|
spaceId,
|
|
19587
20089
|
session,
|
|
19588
20090
|
expiresAt
|
|
@@ -19596,7 +20098,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19596
20098
|
jwk: session.jwk
|
|
19597
20099
|
},
|
|
19598
20100
|
delegation,
|
|
19599
|
-
operations: this.permissionOperations(
|
|
20101
|
+
operations: this.permissionOperations(delegatedEntries, spaceId),
|
|
19600
20102
|
expiresAt
|
|
19601
20103
|
});
|
|
19602
20104
|
delegations.push(delegation);
|
|
@@ -19744,7 +20246,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19744
20246
|
];
|
|
19745
20247
|
const abilities = { kv: { "": kvActions } };
|
|
19746
20248
|
const now = /* @__PURE__ */ new Date();
|
|
19747
|
-
const expiryMs =
|
|
20249
|
+
const expiryMs = EXPIRY3.EPHEMERAL_MS;
|
|
19748
20250
|
const expirationTime = new Date(now.getTime() + expiryMs);
|
|
19749
20251
|
const prepared = this.wasmBindings.prepareSession({
|
|
19750
20252
|
abilities,
|
|
@@ -19914,7 +20416,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19914
20416
|
* `forceWalletSign` is not set.
|
|
19915
20417
|
*/
|
|
19916
20418
|
async delegateTo(did, permissions, options) {
|
|
19917
|
-
const session = this.
|
|
20419
|
+
const session = this.currentTinyCloudSession();
|
|
19918
20420
|
if (!session) {
|
|
19919
20421
|
throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
|
|
19920
20422
|
}
|
|
@@ -19931,10 +20433,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19931
20433
|
"delegateTo requires a non-empty permissions array"
|
|
19932
20434
|
);
|
|
19933
20435
|
}
|
|
19934
|
-
const expandedEntries =
|
|
19935
|
-
...entry,
|
|
19936
|
-
actions: expandActionShortNames(entry.service, entry.actions)
|
|
19937
|
-
}));
|
|
20436
|
+
const expandedEntries = this.expandPermissionEntries(permissions);
|
|
19938
20437
|
const now = /* @__PURE__ */ new Date();
|
|
19939
20438
|
const expiryMs = resolveExpiryMs(options?.expiry);
|
|
19940
20439
|
const expirationTime = new Date(now.getTime() + expiryMs);
|
|
@@ -20031,11 +20530,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20031
20530
|
* the current session; we build one multi-resource abilities map
|
|
20032
20531
|
* and emit one signed UCAN covering them all.
|
|
20033
20532
|
*
|
|
20034
|
-
*
|
|
20035
|
-
*
|
|
20036
|
-
* spaces in a single delegation is not supported by the underlying
|
|
20037
|
-
* Rust create_delegation call and the resulting UCAN would be
|
|
20038
|
-
* under-specified.
|
|
20533
|
+
* Non-encryption entries must share the same target space. Encryption
|
|
20534
|
+
* entries are raw network URNs and do not participate in space grouping.
|
|
20039
20535
|
*
|
|
20040
20536
|
* @internal
|
|
20041
20537
|
*/
|
|
@@ -20047,15 +20543,18 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20047
20543
|
}
|
|
20048
20544
|
const resolvedSpaces = /* @__PURE__ */ new Set();
|
|
20049
20545
|
for (const entry of entries) {
|
|
20546
|
+
if (this.isEncryptionPermissionEntry(entry)) {
|
|
20547
|
+
continue;
|
|
20548
|
+
}
|
|
20050
20549
|
const spaceId2 = this.resolvePermissionSpace(entry.space, session);
|
|
20051
20550
|
resolvedSpaces.add(spaceId2);
|
|
20052
20551
|
}
|
|
20053
|
-
if (resolvedSpaces.size
|
|
20552
|
+
if (resolvedSpaces.size > 1) {
|
|
20054
20553
|
throw new Error(
|
|
20055
20554
|
`delegateTo: all permission entries must target the same space, got ${resolvedSpaces.size}: ${JSON.stringify([...resolvedSpaces])}`
|
|
20056
20555
|
);
|
|
20057
20556
|
}
|
|
20058
|
-
const spaceId = [...resolvedSpaces][0];
|
|
20557
|
+
const spaceId = resolvedSpaces.size === 1 ? [...resolvedSpaces][0] : session.spaceId;
|
|
20059
20558
|
const abilities = {};
|
|
20060
20559
|
for (const entry of entries) {
|
|
20061
20560
|
const shortService = SERVICE_LONG_TO_SHORT[entry.service];
|
|
@@ -20174,10 +20673,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20174
20673
|
return this.wasmBindings.makeSpaceId(session.address, session.chainId, space);
|
|
20175
20674
|
}
|
|
20176
20675
|
expandPermissionEntries(permissions) {
|
|
20177
|
-
return permissions
|
|
20178
|
-
...entry,
|
|
20179
|
-
actions: expandActionShortNames(entry.service, entry.actions)
|
|
20180
|
-
}));
|
|
20676
|
+
return expandPermissionEntriesCore(permissions);
|
|
20181
20677
|
}
|
|
20182
20678
|
shortServiceName(service) {
|
|
20183
20679
|
const short = SERVICE_LONG_TO_SHORT[service];
|
|
@@ -20205,11 +20701,32 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20205
20701
|
}
|
|
20206
20702
|
return abilities;
|
|
20207
20703
|
}
|
|
20704
|
+
isEncryptionPermissionEntry(entry) {
|
|
20705
|
+
return entry.service === ENCRYPTION_PERMISSION_SERVICE2 && entry.path.startsWith("urn:tinycloud:encryption:");
|
|
20706
|
+
}
|
|
20707
|
+
permissionsToRawAbilities(entries) {
|
|
20708
|
+
const rawAbilities = {};
|
|
20709
|
+
for (const entry of entries) {
|
|
20710
|
+
if (!this.isEncryptionPermissionEntry(entry)) {
|
|
20711
|
+
continue;
|
|
20712
|
+
}
|
|
20713
|
+
const existing = rawAbilities[entry.path] ?? [];
|
|
20714
|
+
const seen = new Set(existing);
|
|
20715
|
+
for (const action of entry.actions) {
|
|
20716
|
+
if (!seen.has(action)) {
|
|
20717
|
+
existing.push(action);
|
|
20718
|
+
seen.add(action);
|
|
20719
|
+
}
|
|
20720
|
+
}
|
|
20721
|
+
rawAbilities[entry.path] = existing;
|
|
20722
|
+
}
|
|
20723
|
+
return rawAbilities;
|
|
20724
|
+
}
|
|
20208
20725
|
permissionOperations(entries, spaceId) {
|
|
20209
20726
|
return entries.flatMap((entry) => {
|
|
20210
20727
|
const service = this.shortServiceName(entry.service);
|
|
20211
20728
|
return entry.actions.map((action) => ({
|
|
20212
|
-
spaceId,
|
|
20729
|
+
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId },
|
|
20213
20730
|
service,
|
|
20214
20731
|
path: entry.path,
|
|
20215
20732
|
action
|
|
@@ -20232,7 +20749,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20232
20749
|
const spaceId = this.resolvePermissionSpace(entry.space, session);
|
|
20233
20750
|
const service = this.shortServiceName(entry.service);
|
|
20234
20751
|
return entry.actions.map((action) => ({
|
|
20235
|
-
spaceId,
|
|
20752
|
+
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId },
|
|
20236
20753
|
service,
|
|
20237
20754
|
path: entry.path,
|
|
20238
20755
|
action
|
|
@@ -20289,24 +20806,40 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20289
20806
|
expiresAt: delegation.expiry
|
|
20290
20807
|
};
|
|
20291
20808
|
}
|
|
20809
|
+
installRuntimeGrantFromServiceSession(delegation, session, expiresAt) {
|
|
20810
|
+
const operations = this.operationsFromDelegation(delegation);
|
|
20811
|
+
if (operations.length === 0) {
|
|
20812
|
+
return;
|
|
20813
|
+
}
|
|
20814
|
+
this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
|
|
20815
|
+
(grant) => grant.delegation.cid !== delegation.cid && grant.session.delegationCid !== session.delegationCid
|
|
20816
|
+
);
|
|
20817
|
+
this.runtimePermissionGrants.push({
|
|
20818
|
+
session,
|
|
20819
|
+
delegation,
|
|
20820
|
+
operations,
|
|
20821
|
+
expiresAt
|
|
20822
|
+
});
|
|
20823
|
+
}
|
|
20292
20824
|
delegatedResourcesForEntries(entries, spaceId) {
|
|
20293
20825
|
return entries.map((entry) => ({
|
|
20294
20826
|
service: this.shortServiceName(entry.service),
|
|
20295
|
-
space: spaceId,
|
|
20827
|
+
space: this.isEncryptionPermissionEntry(entry) ? "encryption" : spaceId,
|
|
20296
20828
|
path: entry.path,
|
|
20297
20829
|
actions: [...entry.actions]
|
|
20298
20830
|
}));
|
|
20299
20831
|
}
|
|
20300
20832
|
operationsFromDelegation(delegation) {
|
|
20301
20833
|
const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
|
|
20302
|
-
return resources.flatMap(
|
|
20303
|
-
|
|
20304
|
-
|
|
20305
|
-
service:
|
|
20834
|
+
return resources.flatMap((resource) => {
|
|
20835
|
+
const service = this.invocationServiceName(resource.service);
|
|
20836
|
+
return resource.actions.map((action) => ({
|
|
20837
|
+
...this.isEncryptionNetworkOperation(service, resource.path) ? { resource: resource.path } : { spaceId: resource.space },
|
|
20838
|
+
service,
|
|
20306
20839
|
path: resource.path,
|
|
20307
20840
|
action
|
|
20308
|
-
}))
|
|
20309
|
-
);
|
|
20841
|
+
}));
|
|
20842
|
+
});
|
|
20310
20843
|
}
|
|
20311
20844
|
flatDelegationResources(delegation) {
|
|
20312
20845
|
const byService = /* @__PURE__ */ new Map();
|
|
@@ -20355,7 +20888,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20355
20888
|
);
|
|
20356
20889
|
}
|
|
20357
20890
|
operationCovers(granted, requested) {
|
|
20358
|
-
|
|
20891
|
+
if (granted.service !== requested.service || !this.actionContains(granted.action, requested.action)) {
|
|
20892
|
+
return false;
|
|
20893
|
+
}
|
|
20894
|
+
if (granted.resource !== void 0 || requested.resource !== void 0) {
|
|
20895
|
+
return granted.resource !== void 0 && requested.resource !== void 0 && granted.resource === requested.resource && this.pathContains(granted.path, requested.path);
|
|
20896
|
+
}
|
|
20897
|
+
return granted.spaceId !== void 0 && requested.spaceId !== void 0 && granted.spaceId === requested.spaceId && this.pathContains(granted.path, requested.path);
|
|
20359
20898
|
}
|
|
20360
20899
|
actionContains(grantedAction, requestedAction) {
|
|
20361
20900
|
if (grantedAction === requestedAction) {
|
|
@@ -20370,6 +20909,37 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20370
20909
|
invocationServiceName(service) {
|
|
20371
20910
|
return service.startsWith("tinycloud.") ? this.shortServiceName(service) : service;
|
|
20372
20911
|
}
|
|
20912
|
+
isEncryptionNetworkOperation(service, path) {
|
|
20913
|
+
return service === "encryption" && path.startsWith("urn:tinycloud:encryption:");
|
|
20914
|
+
}
|
|
20915
|
+
operationFromInvokeAnyEntry(entry) {
|
|
20916
|
+
const service = this.invocationServiceName(entry.service);
|
|
20917
|
+
if (typeof entry.resource === "string") {
|
|
20918
|
+
return {
|
|
20919
|
+
resource: entry.resource,
|
|
20920
|
+
service,
|
|
20921
|
+
path: entry.path,
|
|
20922
|
+
action: entry.action
|
|
20923
|
+
};
|
|
20924
|
+
}
|
|
20925
|
+
if (this.isEncryptionNetworkOperation(service, entry.path)) {
|
|
20926
|
+
return {
|
|
20927
|
+
resource: entry.path,
|
|
20928
|
+
service,
|
|
20929
|
+
path: entry.path,
|
|
20930
|
+
action: entry.action
|
|
20931
|
+
};
|
|
20932
|
+
}
|
|
20933
|
+
if (typeof entry.spaceId === "string") {
|
|
20934
|
+
return {
|
|
20935
|
+
spaceId: entry.spaceId,
|
|
20936
|
+
service,
|
|
20937
|
+
path: entry.path,
|
|
20938
|
+
action: entry.action
|
|
20939
|
+
};
|
|
20940
|
+
}
|
|
20941
|
+
return void 0;
|
|
20942
|
+
}
|
|
20373
20943
|
pathContains(grantedPath, requestedPath) {
|
|
20374
20944
|
if (grantedPath === "" || grantedPath === "/") {
|
|
20375
20945
|
return true;
|
|
@@ -20608,6 +21178,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20608
21178
|
// Not used in session-only mode
|
|
20609
21179
|
};
|
|
20610
21180
|
this.trackReceivedDelegation(delegation, this.sessionKeyJwk);
|
|
21181
|
+
this.installRuntimeGrantFromServiceSession(
|
|
21182
|
+
delegation,
|
|
21183
|
+
{
|
|
21184
|
+
delegationHeader: session2.delegationHeader,
|
|
21185
|
+
delegationCid: session2.delegationCid,
|
|
21186
|
+
spaceId: session2.spaceId,
|
|
21187
|
+
verificationMethod: session2.verificationMethod,
|
|
21188
|
+
jwk: session2.jwk
|
|
21189
|
+
},
|
|
21190
|
+
delegation.expiry
|
|
21191
|
+
);
|
|
20611
21192
|
return new DelegatedAccess(session2, delegation, targetHost, this.wasmBindings.invoke);
|
|
20612
21193
|
}
|
|
20613
21194
|
const mySession = this.auth?.tinyCloudSession;
|
|
@@ -20619,6 +21200,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20619
21200
|
const kvActions = delegation.actions.filter((a) => a.startsWith("tinycloud.kv/"));
|
|
20620
21201
|
const sqlActions = delegation.actions.filter((a) => a.startsWith("tinycloud.sql/"));
|
|
20621
21202
|
const duckdbActions = delegation.actions.filter((a) => a.startsWith("tinycloud.duckdb/"));
|
|
21203
|
+
const encryptionActions = delegation.actions.filter(
|
|
21204
|
+
(a) => a.startsWith("tinycloud.encryption/")
|
|
21205
|
+
);
|
|
21206
|
+
const rawAbilities = {};
|
|
20622
21207
|
if (kvActions.length > 0) {
|
|
20623
21208
|
abilities.kv = { [delegation.path]: kvActions };
|
|
20624
21209
|
}
|
|
@@ -20628,6 +21213,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20628
21213
|
if (duckdbActions.length > 0) {
|
|
20629
21214
|
abilities.duckdb = { [delegation.path]: duckdbActions };
|
|
20630
21215
|
}
|
|
21216
|
+
if (encryptionActions.length > 0 && delegation.path.startsWith("urn:tinycloud:encryption:")) {
|
|
21217
|
+
rawAbilities[delegation.path] = encryptionActions;
|
|
21218
|
+
}
|
|
20631
21219
|
const now = /* @__PURE__ */ new Date();
|
|
20632
21220
|
const maxExpiry = new Date(now.getTime() + 60 * 60 * 1e3);
|
|
20633
21221
|
const expirationTime = delegation.expiry < maxExpiry ? delegation.expiry : maxExpiry;
|
|
@@ -20640,7 +21228,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20640
21228
|
expirationTime: expirationTime.toISOString(),
|
|
20641
21229
|
spaceId: delegation.spaceId,
|
|
20642
21230
|
jwk,
|
|
20643
|
-
parents: [delegation.cid]
|
|
21231
|
+
parents: [delegation.cid],
|
|
21232
|
+
...Object.keys(rawAbilities).length > 0 ? { rawAbilities } : {}
|
|
20644
21233
|
});
|
|
20645
21234
|
const signature2 = await this.signer.signMessage(prepared.siwe);
|
|
20646
21235
|
const invokerSession = this.wasmBindings.completeSessionSetup({
|
|
@@ -20667,6 +21256,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20667
21256
|
signature: signature2
|
|
20668
21257
|
};
|
|
20669
21258
|
this.trackReceivedDelegation(delegation, jwk);
|
|
21259
|
+
this.installRuntimeGrantFromServiceSession(
|
|
21260
|
+
delegation,
|
|
21261
|
+
{
|
|
21262
|
+
delegationHeader: session.delegationHeader,
|
|
21263
|
+
delegationCid: session.delegationCid,
|
|
21264
|
+
spaceId: session.spaceId,
|
|
21265
|
+
verificationMethod: session.verificationMethod,
|
|
21266
|
+
jwk: session.jwk
|
|
21267
|
+
},
|
|
21268
|
+
expirationTime
|
|
21269
|
+
);
|
|
20670
21270
|
return new DelegatedAccess(session, delegation, targetHost, this.wasmBindings.invoke);
|
|
20671
21271
|
}
|
|
20672
21272
|
/**
|
|
@@ -20911,6 +21511,7 @@ import {
|
|
|
20911
21511
|
ACCOUNT_REGISTRY_SPACE as ACCOUNT_REGISTRY_SPACE2,
|
|
20912
21512
|
DEFAULT_MANIFEST_SPACE as DEFAULT_MANIFEST_SPACE2,
|
|
20913
21513
|
DEFAULT_MANIFEST_VERSION,
|
|
21514
|
+
VAULT_PERMISSION_SERVICE,
|
|
20914
21515
|
PermissionNotInManifestError as PermissionNotInManifestError2,
|
|
20915
21516
|
SessionExpiredError as SessionExpiredError2,
|
|
20916
21517
|
ManifestValidationError,
|
|
@@ -20919,7 +21520,9 @@ import {
|
|
|
20919
21520
|
validateManifest,
|
|
20920
21521
|
loadManifest,
|
|
20921
21522
|
isCapabilitySubset as isCapabilitySubset2,
|
|
20922
|
-
expandActionShortNames
|
|
21523
|
+
expandActionShortNames,
|
|
21524
|
+
expandPermissionEntries as expandPermissionEntries2,
|
|
21525
|
+
expandPermissionEntry,
|
|
20923
21526
|
parseExpiry as parseExpiry2,
|
|
20924
21527
|
resourceCapabilitiesToSpaceAbilitiesMap as resourceCapabilitiesToSpaceAbilitiesMap2
|
|
20925
21528
|
} from "@tinycloud/sdk-core";
|
|
@@ -20941,7 +21544,11 @@ function deserializeDelegation(data) {
|
|
|
20941
21544
|
}
|
|
20942
21545
|
|
|
20943
21546
|
// src/index.ts
|
|
20944
|
-
import {
|
|
21547
|
+
import {
|
|
21548
|
+
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
21549
|
+
KVService as KVService3,
|
|
21550
|
+
PrefixedKVService
|
|
21551
|
+
} from "@tinycloud/sdk-core";
|
|
20945
21552
|
import { SQLService as SQLService3, SQLAction, DatabaseHandle } from "@tinycloud/sdk-core";
|
|
20946
21553
|
import {
|
|
20947
21554
|
DuckDbService as DuckDbService3,
|
|
@@ -20953,7 +21560,53 @@ import {
|
|
|
20953
21560
|
VaultHeaders,
|
|
20954
21561
|
VaultPublicSpaceKVActions,
|
|
20955
21562
|
createVaultCrypto as createVaultCrypto2,
|
|
20956
|
-
SecretsService as SecretsService2
|
|
21563
|
+
SecretsService as SecretsService2,
|
|
21564
|
+
SECRET_NAME_RE,
|
|
21565
|
+
canonicalizeSecretScope,
|
|
21566
|
+
resolveSecretListPrefix as resolveSecretListPrefix2,
|
|
21567
|
+
resolveSecretPath as resolveSecretPath2
|
|
21568
|
+
} from "@tinycloud/sdk-core";
|
|
21569
|
+
import {
|
|
21570
|
+
EncryptionService as EncryptionService2,
|
|
21571
|
+
parseNetworkId,
|
|
21572
|
+
buildNetworkId,
|
|
21573
|
+
isNetworkId,
|
|
21574
|
+
networkDiscoveryKey,
|
|
21575
|
+
NetworkIdError,
|
|
21576
|
+
ENCRYPTION_NETWORK_URN_PREFIX,
|
|
21577
|
+
NETWORK_NAME_PATTERN,
|
|
21578
|
+
canonicalizeEncryptionJson as canonicalizeEncryptionJson2,
|
|
21579
|
+
canonicalHashHex as canonicalHashHex2,
|
|
21580
|
+
hexEncode,
|
|
21581
|
+
hexDecode,
|
|
21582
|
+
encryptionBase64Encode,
|
|
21583
|
+
encryptionBase64Decode,
|
|
21584
|
+
encryptionUtf8Encode,
|
|
21585
|
+
encryptionUtf8Decode,
|
|
21586
|
+
encryptToNetwork,
|
|
21587
|
+
decryptEnvelopeWithKey,
|
|
21588
|
+
validateEnvelope,
|
|
21589
|
+
generateRandomReceiverKey,
|
|
21590
|
+
deriveSignedReceiverKey,
|
|
21591
|
+
buildCanonicalDecryptRequest,
|
|
21592
|
+
buildDecryptFacts,
|
|
21593
|
+
buildDecryptAttenuation,
|
|
21594
|
+
buildDecryptInvocation,
|
|
21595
|
+
checkDecryptInvocationInput,
|
|
21596
|
+
verifyDecryptResponse,
|
|
21597
|
+
canonicalSignedResponse,
|
|
21598
|
+
openWrappedKey,
|
|
21599
|
+
discoverNetwork,
|
|
21600
|
+
ensureNetworkUsableForDecrypt,
|
|
21601
|
+
DEFAULT_ENCRYPTION_ALG,
|
|
21602
|
+
ENVELOPE_VERSION,
|
|
21603
|
+
DEFAULT_KEY_VERSION,
|
|
21604
|
+
DECRYPT_FACT_TYPE,
|
|
21605
|
+
DECRYPT_RESULT_TYPE,
|
|
21606
|
+
DECRYPT_ACTION as DECRYPT_ACTION2,
|
|
21607
|
+
ENCRYPTION_SERVICE,
|
|
21608
|
+
ENCRYPTION_SERVICE_SHORT,
|
|
21609
|
+
encryptionError
|
|
20957
21610
|
} from "@tinycloud/sdk-core";
|
|
20958
21611
|
import { HooksService as HooksService3 } from "@tinycloud/sdk-core";
|
|
20959
21612
|
import {
|
|
@@ -20989,8 +21642,14 @@ export {
|
|
|
20989
21642
|
AutoApproveSpaceCreationHandler2 as AutoApproveSpaceCreationHandler,
|
|
20990
21643
|
CapabilityKeyRegistry2 as CapabilityKeyRegistry,
|
|
20991
21644
|
CapabilityKeyRegistryErrorCodes,
|
|
21645
|
+
DECRYPT_ACTION2 as DECRYPT_ACTION,
|
|
21646
|
+
DECRYPT_FACT_TYPE,
|
|
21647
|
+
DECRYPT_RESULT_TYPE,
|
|
21648
|
+
DEFAULT_ENCRYPTION_ALG,
|
|
21649
|
+
DEFAULT_KEY_VERSION,
|
|
20992
21650
|
DEFAULT_MANIFEST_SPACE2 as DEFAULT_MANIFEST_SPACE,
|
|
20993
21651
|
DEFAULT_MANIFEST_VERSION,
|
|
21652
|
+
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
20994
21653
|
DataVaultService2 as DataVaultService,
|
|
20995
21654
|
DatabaseHandle,
|
|
20996
21655
|
DelegatedAccess,
|
|
@@ -20999,17 +21658,25 @@ export {
|
|
|
20999
21658
|
DuckDbAction,
|
|
21000
21659
|
DuckDbDatabaseHandle,
|
|
21001
21660
|
DuckDbService3 as DuckDbService,
|
|
21661
|
+
ENCRYPTION_NETWORK_URN_PREFIX,
|
|
21662
|
+
ENCRYPTION_SERVICE,
|
|
21663
|
+
ENCRYPTION_SERVICE_SHORT,
|
|
21664
|
+
ENVELOPE_VERSION,
|
|
21665
|
+
EncryptionService2 as EncryptionService,
|
|
21002
21666
|
FileSessionStorage,
|
|
21003
21667
|
HooksService3 as HooksService,
|
|
21004
21668
|
KVService3 as KVService,
|
|
21005
21669
|
ManifestValidationError,
|
|
21006
21670
|
MemorySessionStorage,
|
|
21671
|
+
NETWORK_NAME_PATTERN,
|
|
21672
|
+
NetworkIdError,
|
|
21007
21673
|
NodeUserAuthorization,
|
|
21008
21674
|
NodeWasmBindings,
|
|
21009
21675
|
PermissionNotInManifestError2 as PermissionNotInManifestError,
|
|
21010
21676
|
PrefixedKVService,
|
|
21011
21677
|
PrivateKeySigner,
|
|
21012
21678
|
ProtocolMismatchError,
|
|
21679
|
+
SECRET_NAME_RE,
|
|
21013
21680
|
SQLAction,
|
|
21014
21681
|
SQLService3 as SQLService,
|
|
21015
21682
|
SecretsService2 as SecretsService,
|
|
@@ -21023,11 +21690,22 @@ export {
|
|
|
21023
21690
|
TinyCloud2 as TinyCloud,
|
|
21024
21691
|
TinyCloudNode,
|
|
21025
21692
|
UnsupportedFeatureError2 as UnsupportedFeatureError,
|
|
21693
|
+
VAULT_PERMISSION_SERVICE,
|
|
21026
21694
|
VaultHeaders,
|
|
21027
21695
|
VaultPublicSpaceKVActions,
|
|
21028
21696
|
VersionCheckError,
|
|
21029
21697
|
WasmKeyProvider,
|
|
21698
|
+
buildCanonicalDecryptRequest,
|
|
21699
|
+
buildDecryptAttenuation,
|
|
21700
|
+
buildDecryptFacts,
|
|
21701
|
+
buildDecryptInvocation,
|
|
21702
|
+
buildNetworkId,
|
|
21030
21703
|
buildSpaceUri,
|
|
21704
|
+
canonicalHashHex2 as canonicalHashHex,
|
|
21705
|
+
canonicalSignedResponse,
|
|
21706
|
+
canonicalizeEncryptionJson2 as canonicalizeEncryptionJson,
|
|
21707
|
+
canonicalizeSecretScope,
|
|
21708
|
+
checkDecryptInvocationInput,
|
|
21031
21709
|
checkNodeInfo2 as checkNodeInfo,
|
|
21032
21710
|
composeManifestRequest2 as composeManifestRequest,
|
|
21033
21711
|
createCapabilityKeyRegistry,
|
|
@@ -21035,19 +21713,42 @@ export {
|
|
|
21035
21713
|
createSpaceService,
|
|
21036
21714
|
createVaultCrypto2 as createVaultCrypto,
|
|
21037
21715
|
createWasmKeyProvider,
|
|
21716
|
+
decryptEnvelopeWithKey,
|
|
21038
21717
|
defaultSignStrategy,
|
|
21039
21718
|
defaultSpaceCreationHandler,
|
|
21719
|
+
deriveSignedReceiverKey,
|
|
21040
21720
|
deserializeDelegation,
|
|
21041
|
-
|
|
21721
|
+
discoverNetwork,
|
|
21722
|
+
encryptToNetwork,
|
|
21723
|
+
encryptionBase64Decode,
|
|
21724
|
+
encryptionBase64Encode,
|
|
21725
|
+
encryptionError,
|
|
21726
|
+
encryptionUtf8Decode,
|
|
21727
|
+
encryptionUtf8Encode,
|
|
21728
|
+
ensureNetworkUsableForDecrypt,
|
|
21729
|
+
expandActionShortNames,
|
|
21730
|
+
expandPermissionEntries2 as expandPermissionEntries,
|
|
21731
|
+
expandPermissionEntry,
|
|
21732
|
+
generateRandomReceiverKey,
|
|
21733
|
+
hexDecode,
|
|
21734
|
+
hexEncode,
|
|
21042
21735
|
isCapabilitySubset2 as isCapabilitySubset,
|
|
21736
|
+
isNetworkId,
|
|
21043
21737
|
loadManifest,
|
|
21044
21738
|
makePublicSpaceId2 as makePublicSpaceId,
|
|
21739
|
+
networkDiscoveryKey,
|
|
21740
|
+
openWrappedKey,
|
|
21045
21741
|
parseExpiry2 as parseExpiry,
|
|
21742
|
+
parseNetworkId,
|
|
21046
21743
|
parseSpaceUri,
|
|
21047
21744
|
resolveManifest2 as resolveManifest,
|
|
21745
|
+
resolveSecretListPrefix2 as resolveSecretListPrefix,
|
|
21746
|
+
resolveSecretPath2 as resolveSecretPath,
|
|
21048
21747
|
resourceCapabilitiesToSpaceAbilitiesMap2 as resourceCapabilitiesToSpaceAbilitiesMap,
|
|
21049
21748
|
serializeDelegation,
|
|
21050
|
-
|
|
21749
|
+
validateEnvelope,
|
|
21750
|
+
validateManifest,
|
|
21751
|
+
verifyDecryptResponse
|
|
21051
21752
|
};
|
|
21052
21753
|
/*! Bundled license information:
|
|
21053
21754
|
|