@tinycloud/node-sdk 2.2.0-beta.9 → 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 +708 -92
- 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 +726 -99
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +802 -114
- 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 +805 -100
- 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 };
|
|
@@ -18265,27 +18341,39 @@ function secretsError(code, message, cause) {
|
|
|
18265
18341
|
};
|
|
18266
18342
|
}
|
|
18267
18343
|
function displayActionUrn(action) {
|
|
18268
|
-
|
|
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
|
-
|
|
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"],
|
|
18280
18373
|
skipPrefix: true
|
|
18281
|
-
}
|
|
18282
|
-
|
|
18283
|
-
|
|
18284
|
-
function secretResourcePath(base2, name) {
|
|
18285
|
-
return `${base2}/${SECRET_PREFIX}${name}`;
|
|
18286
|
-
}
|
|
18287
|
-
function isSecretsSpace(space) {
|
|
18288
|
-
return space === SECRETS_SPACE || space.endsWith(`:${SECRETS_SPACE}`);
|
|
18374
|
+
});
|
|
18375
|
+
}
|
|
18376
|
+
return entries;
|
|
18289
18377
|
}
|
|
18290
18378
|
var NodeSecretsService = class {
|
|
18291
18379
|
constructor(config) {
|
|
@@ -18313,48 +18401,62 @@ var NodeSecretsService = class {
|
|
|
18313
18401
|
this.shouldRestoreUnlock = false;
|
|
18314
18402
|
this.service.lock();
|
|
18315
18403
|
}
|
|
18316
|
-
get(name) {
|
|
18317
|
-
|
|
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);
|
|
18318
18408
|
}
|
|
18319
|
-
async put(name, value) {
|
|
18320
|
-
const permission = await this.
|
|
18409
|
+
async put(name, value, options) {
|
|
18410
|
+
const permission = await this.ensurePermission(name, options, "put");
|
|
18321
18411
|
if (!permission.ok) return permission;
|
|
18322
|
-
return this.service.put(name, value);
|
|
18412
|
+
return options === void 0 ? this.service.put(name, value) : this.service.put(name, value, options);
|
|
18323
18413
|
}
|
|
18324
|
-
async delete(name) {
|
|
18325
|
-
const permission = await this.
|
|
18414
|
+
async delete(name, options) {
|
|
18415
|
+
const permission = await this.ensurePermission(name, options, "del");
|
|
18326
18416
|
if (!permission.ok) return permission;
|
|
18327
|
-
return this.service.delete(name);
|
|
18417
|
+
return options === void 0 ? this.service.delete(name) : this.service.delete(name, options);
|
|
18328
18418
|
}
|
|
18329
|
-
list() {
|
|
18330
|
-
|
|
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);
|
|
18331
18423
|
}
|
|
18332
18424
|
get service() {
|
|
18333
18425
|
return this.config.getService();
|
|
18334
18426
|
}
|
|
18335
|
-
async
|
|
18336
|
-
|
|
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) {
|
|
18337
18438
|
return secretsError(
|
|
18338
18439
|
ErrorCodes.INVALID_INPUT,
|
|
18339
|
-
|
|
18440
|
+
error instanceof Error ? error.message : String(error),
|
|
18441
|
+
error instanceof Error ? error : void 0
|
|
18340
18442
|
);
|
|
18341
18443
|
}
|
|
18342
|
-
if (this.
|
|
18444
|
+
if (this.hasPermission(permissionEntries)) {
|
|
18343
18445
|
return ok();
|
|
18344
18446
|
}
|
|
18345
18447
|
if (!this.config.canEscalate()) {
|
|
18346
18448
|
return secretsError(
|
|
18347
18449
|
ErrorCodes.PERMISSION_DENIED,
|
|
18348
|
-
`Cannot autosign ${displayActionUrn(action)} for ${
|
|
18450
|
+
`Cannot autosign ${displayActionUrn(action)} for ${target}; TinyCloudNode needs wallet mode with a signer or privateKey.`
|
|
18349
18451
|
);
|
|
18350
18452
|
}
|
|
18351
18453
|
try {
|
|
18352
|
-
await this.config.grantPermissions(
|
|
18454
|
+
await this.config.grantPermissions(permissionEntries);
|
|
18353
18455
|
return this.restoreUnlockAfterEscalation();
|
|
18354
18456
|
} catch (error) {
|
|
18355
18457
|
return secretsError(
|
|
18356
18458
|
ErrorCodes.PERMISSION_DENIED,
|
|
18357
|
-
error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${
|
|
18459
|
+
error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${target} failed.`,
|
|
18358
18460
|
error instanceof Error ? error : void 0
|
|
18359
18461
|
);
|
|
18360
18462
|
}
|
|
@@ -18365,26 +18467,117 @@ var NodeSecretsService = class {
|
|
|
18365
18467
|
}
|
|
18366
18468
|
return this.service.unlock(this.unlockSigner);
|
|
18367
18469
|
}
|
|
18368
|
-
|
|
18470
|
+
hasPermission(permissionEntries) {
|
|
18471
|
+
if (this.config.hasPermissions?.(permissionEntries)) {
|
|
18472
|
+
return true;
|
|
18473
|
+
}
|
|
18369
18474
|
const manifest = this.config.getManifest();
|
|
18370
18475
|
if (manifest === void 0) {
|
|
18371
18476
|
return false;
|
|
18372
18477
|
}
|
|
18373
18478
|
const manifests = Array.isArray(manifest) ? manifest : [manifest];
|
|
18374
|
-
const
|
|
18375
|
-
return
|
|
18376
|
-
|
|
18377
|
-
|
|
18378
|
-
|
|
18379
|
-
(resource) => resource.service ===
|
|
18380
|
-
)
|
|
18381
|
-
)
|
|
18382
|
-
|
|
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
|
+
);
|
|
18383
18488
|
}
|
|
18384
18489
|
};
|
|
18385
18490
|
|
|
18386
18491
|
// src/TinyCloudNode.ts
|
|
18387
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
|
+
}
|
|
18388
18581
|
var _TinyCloudNode = class _TinyCloudNode {
|
|
18389
18582
|
/**
|
|
18390
18583
|
* Create a new TinyCloudNode instance.
|
|
@@ -18429,12 +18622,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18429
18622
|
throw new Error("WASM binding does not support invokeAny");
|
|
18430
18623
|
}
|
|
18431
18624
|
const grant = this.findGrantForOperations(
|
|
18432
|
-
entries.
|
|
18433
|
-
|
|
18434
|
-
|
|
18435
|
-
|
|
18436
|
-
action: entry.action
|
|
18437
|
-
}))
|
|
18625
|
+
entries.flatMap((entry) => {
|
|
18626
|
+
const operation = this.operationFromInvokeAnyEntry(entry);
|
|
18627
|
+
return operation ? [operation] : [];
|
|
18628
|
+
})
|
|
18438
18629
|
);
|
|
18439
18630
|
return this.wasmBindings.invokeAny(grant?.session ?? session, entries, facts);
|
|
18440
18631
|
};
|
|
@@ -18527,7 +18718,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18527
18718
|
sessionStorage: config.sessionStorage ?? new MemorySessionStorage(),
|
|
18528
18719
|
domain: this.siweDomain,
|
|
18529
18720
|
spacePrefix: config.prefix,
|
|
18530
|
-
sessionExpirationMs: config.sessionExpirationMs ??
|
|
18721
|
+
sessionExpirationMs: config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
|
|
18531
18722
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
18532
18723
|
tinycloudRegistryUrl: config.tinycloudRegistryUrl,
|
|
18533
18724
|
tinycloudFallbackHosts: config.tinycloudFallbackHosts,
|
|
@@ -18662,6 +18853,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18662
18853
|
this._duckdb = void 0;
|
|
18663
18854
|
this._hooks = void 0;
|
|
18664
18855
|
this._vault = void 0;
|
|
18856
|
+
this._encryption = void 0;
|
|
18665
18857
|
this._baseSecrets = void 0;
|
|
18666
18858
|
this._secrets = void 0;
|
|
18667
18859
|
this._spaceService = void 0;
|
|
@@ -18670,6 +18862,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18670
18862
|
await this.tc.signIn(options);
|
|
18671
18863
|
this.syncResolvedHostFromAuth();
|
|
18672
18864
|
this.initializeServices();
|
|
18865
|
+
if (this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
|
|
18866
|
+
await this.ensureOwnedSpaceHosted(this.ownedSpaceId("secrets"));
|
|
18867
|
+
}
|
|
18673
18868
|
await this.writeManifestRegistryRecords();
|
|
18674
18869
|
this.notificationHandler.success("Successfully signed in");
|
|
18675
18870
|
}
|
|
@@ -18752,6 +18947,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18752
18947
|
this._duckdb = void 0;
|
|
18753
18948
|
this._hooks = void 0;
|
|
18754
18949
|
this._vault = void 0;
|
|
18950
|
+
this._encryption = void 0;
|
|
18755
18951
|
this._baseSecrets = void 0;
|
|
18756
18952
|
this._secrets = void 0;
|
|
18757
18953
|
this._spaceService = void 0;
|
|
@@ -18793,6 +18989,33 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18793
18989
|
this._vault.initialize(this._serviceContext);
|
|
18794
18990
|
this._serviceContext.registerService("vault", this._vault);
|
|
18795
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;
|
|
18796
19019
|
}
|
|
18797
19020
|
/**
|
|
18798
19021
|
* Connect a wallet to upgrade from session-only mode to wallet mode.
|
|
@@ -18837,7 +19060,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18837
19060
|
sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
|
|
18838
19061
|
domain: this.siweDomain,
|
|
18839
19062
|
spacePrefix: prefix,
|
|
18840
|
-
sessionExpirationMs: this.config.sessionExpirationMs ??
|
|
19063
|
+
sessionExpirationMs: this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
|
|
18841
19064
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
18842
19065
|
tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
|
|
18843
19066
|
tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
|
|
@@ -18881,7 +19104,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18881
19104
|
sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
|
|
18882
19105
|
domain: this.siweDomain,
|
|
18883
19106
|
spacePrefix: prefix,
|
|
18884
|
-
sessionExpirationMs: this.config.sessionExpirationMs ??
|
|
19107
|
+
sessionExpirationMs: this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
|
|
18885
19108
|
tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
|
|
18886
19109
|
tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
|
|
18887
19110
|
tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
|
|
@@ -18904,7 +19127,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18904
19127
|
* @internal
|
|
18905
19128
|
*/
|
|
18906
19129
|
initializeServices() {
|
|
18907
|
-
const session = this.
|
|
19130
|
+
const session = this.currentTinyCloudSession();
|
|
18908
19131
|
if (!session) {
|
|
18909
19132
|
return;
|
|
18910
19133
|
}
|
|
@@ -18962,6 +19185,163 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18962
19185
|
}
|
|
18963
19186
|
return kvService;
|
|
18964
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
|
+
}
|
|
18965
19345
|
createVaultService(spaceId, kv) {
|
|
18966
19346
|
const wasm = this.wasmBindings;
|
|
18967
19347
|
const vaultCrypto = createVaultCrypto({
|
|
@@ -18977,6 +19357,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
18977
19357
|
return new DataVaultService({
|
|
18978
19358
|
spaceId,
|
|
18979
19359
|
crypto: vaultCrypto,
|
|
19360
|
+
encryption: {
|
|
19361
|
+
networkId: this.getDefaultEncryptionNetworkId(),
|
|
19362
|
+
service: this.getEncryptionService(),
|
|
19363
|
+
decryptCapabilityProof: () => ({
|
|
19364
|
+
proofs: [this.requireServiceSession().delegationCid]
|
|
19365
|
+
})
|
|
19366
|
+
},
|
|
18980
19367
|
tc: {
|
|
18981
19368
|
kv,
|
|
18982
19369
|
ensurePublicSpace: async () => {
|
|
@@ -19157,7 +19544,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19157
19544
|
* @internal
|
|
19158
19545
|
*/
|
|
19159
19546
|
getSessionExpiry() {
|
|
19160
|
-
const expirationMs = this.config.sessionExpirationMs ??
|
|
19547
|
+
const expirationMs = this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS;
|
|
19161
19548
|
return new Date(Date.now() + expirationMs);
|
|
19162
19549
|
}
|
|
19163
19550
|
/**
|
|
@@ -19214,7 +19601,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19214
19601
|
if (!this.signer) {
|
|
19215
19602
|
return void 0;
|
|
19216
19603
|
}
|
|
19217
|
-
const session = this.
|
|
19604
|
+
const session = this.currentTinyCloudSession();
|
|
19218
19605
|
if (!session) {
|
|
19219
19606
|
return void 0;
|
|
19220
19607
|
}
|
|
@@ -19314,6 +19701,34 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19314
19701
|
}
|
|
19315
19702
|
return this._sql;
|
|
19316
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
|
+
}
|
|
19317
19732
|
/**
|
|
19318
19733
|
* DuckDB database operations on this user's space.
|
|
19319
19734
|
*/
|
|
@@ -19337,6 +19752,79 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19337
19752
|
}
|
|
19338
19753
|
return this._vault;
|
|
19339
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
|
+
}
|
|
19340
19828
|
/**
|
|
19341
19829
|
* App-facing secrets API backed by the `secrets` space vault.
|
|
19342
19830
|
*/
|
|
@@ -19348,8 +19836,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19348
19836
|
this._secrets = new NodeSecretsService({
|
|
19349
19837
|
getService: () => this.getBaseSecrets(),
|
|
19350
19838
|
getManifest: () => this.manifest,
|
|
19839
|
+
hasPermissions: (permissions) => this.hasRuntimePermissions(permissions),
|
|
19351
19840
|
grantPermissions: (additional) => this.grantRuntimePermissions(additional),
|
|
19352
19841
|
canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
|
|
19842
|
+
getEncryptionNetworkId: () => this.getDefaultEncryptionNetworkId(),
|
|
19353
19843
|
getUnlockSigner: () => this.signer ?? void 0
|
|
19354
19844
|
});
|
|
19355
19845
|
}
|
|
@@ -19439,7 +19929,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19439
19929
|
* every requested permission.
|
|
19440
19930
|
*/
|
|
19441
19931
|
hasRuntimePermissions(permissions) {
|
|
19442
|
-
const session = this.
|
|
19932
|
+
const session = this.currentTinyCloudSession();
|
|
19443
19933
|
if (!session || !Array.isArray(permissions) || permissions.length === 0) {
|
|
19444
19934
|
return false;
|
|
19445
19935
|
}
|
|
@@ -19459,7 +19949,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19459
19949
|
if (permissions === void 0) {
|
|
19460
19950
|
return this.runtimePermissionGrants.map((grant) => grant.delegation);
|
|
19461
19951
|
}
|
|
19462
|
-
const session = this.
|
|
19952
|
+
const session = this.currentTinyCloudSession();
|
|
19463
19953
|
if (!session || !Array.isArray(permissions) || permissions.length === 0) {
|
|
19464
19954
|
return [];
|
|
19465
19955
|
}
|
|
@@ -19473,7 +19963,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19473
19963
|
* matching service calls and downstream `delegateTo()` calls can use it.
|
|
19474
19964
|
*/
|
|
19475
19965
|
async useRuntimeDelegation(delegation) {
|
|
19476
|
-
const session = this.
|
|
19966
|
+
const session = this.currentTinyCloudSession();
|
|
19477
19967
|
if (!session) {
|
|
19478
19968
|
throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
|
|
19479
19969
|
}
|
|
@@ -19512,7 +20002,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19512
20002
|
if (!Array.isArray(permissions) || permissions.length === 0) {
|
|
19513
20003
|
throw new Error("grantRuntimePermissions requires a non-empty permissions array");
|
|
19514
20004
|
}
|
|
19515
|
-
const session = this.
|
|
20005
|
+
const session = this.currentTinyCloudSession();
|
|
19516
20006
|
if (!session) {
|
|
19517
20007
|
throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
|
|
19518
20008
|
}
|
|
@@ -19536,13 +20026,22 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19536
20026
|
"grantRuntimePermissions requires wallet mode with a signer or privateKey."
|
|
19537
20027
|
);
|
|
19538
20028
|
}
|
|
20029
|
+
const rawEntries = expanded.filter(
|
|
20030
|
+
(entry) => this.isEncryptionPermissionEntry(entry)
|
|
20031
|
+
);
|
|
20032
|
+
const spaceEntries = expanded.filter(
|
|
20033
|
+
(entry) => !this.isEncryptionPermissionEntry(entry)
|
|
20034
|
+
);
|
|
19539
20035
|
const bySpace = /* @__PURE__ */ new Map();
|
|
19540
|
-
for (const entry of
|
|
20036
|
+
for (const entry of spaceEntries) {
|
|
19541
20037
|
const spaceId = this.resolvePermissionSpace(entry.space, session);
|
|
19542
20038
|
const current = bySpace.get(spaceId) ?? [];
|
|
19543
20039
|
current.push(entry);
|
|
19544
20040
|
bySpace.set(spaceId, current);
|
|
19545
20041
|
}
|
|
20042
|
+
if (bySpace.size === 0 && rawEntries.length > 0) {
|
|
20043
|
+
bySpace.set(session.spaceId, []);
|
|
20044
|
+
}
|
|
19546
20045
|
const now = /* @__PURE__ */ new Date();
|
|
19547
20046
|
const requestedExpiryMs = resolveExpiryMs(options?.expiry);
|
|
19548
20047
|
let expiresAt = new Date(now.getTime() + requestedExpiryMs);
|
|
@@ -19550,10 +20049,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19550
20049
|
expiresAt = sessionExpiry;
|
|
19551
20050
|
}
|
|
19552
20051
|
const delegations = [];
|
|
20052
|
+
let rawEntriesAttached = false;
|
|
19553
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];
|
|
19554
20059
|
const abilities = this.permissionsToAbilities(entries);
|
|
19555
20060
|
const prepared = this.wasmBindings.prepareSession({
|
|
19556
20061
|
abilities,
|
|
20062
|
+
...rawForDelegation.length > 0 ? { rawAbilities: this.permissionsToRawAbilities(rawForDelegation) } : {},
|
|
19557
20063
|
address: this.wasmBindings.ensureEip55(session.address),
|
|
19558
20064
|
chainId: session.chainId,
|
|
19559
20065
|
domain: this.siweDomain,
|
|
@@ -19578,7 +20084,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19578
20084
|
}
|
|
19579
20085
|
const delegation = this.runtimeDelegationFromSession(
|
|
19580
20086
|
delegatedSession,
|
|
19581
|
-
|
|
20087
|
+
delegatedEntries,
|
|
19582
20088
|
spaceId,
|
|
19583
20089
|
session,
|
|
19584
20090
|
expiresAt
|
|
@@ -19592,7 +20098,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19592
20098
|
jwk: session.jwk
|
|
19593
20099
|
},
|
|
19594
20100
|
delegation,
|
|
19595
|
-
operations: this.permissionOperations(
|
|
20101
|
+
operations: this.permissionOperations(delegatedEntries, spaceId),
|
|
19596
20102
|
expiresAt
|
|
19597
20103
|
});
|
|
19598
20104
|
delegations.push(delegation);
|
|
@@ -19740,7 +20246,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19740
20246
|
];
|
|
19741
20247
|
const abilities = { kv: { "": kvActions } };
|
|
19742
20248
|
const now = /* @__PURE__ */ new Date();
|
|
19743
|
-
const expiryMs =
|
|
20249
|
+
const expiryMs = EXPIRY3.EPHEMERAL_MS;
|
|
19744
20250
|
const expirationTime = new Date(now.getTime() + expiryMs);
|
|
19745
20251
|
const prepared = this.wasmBindings.prepareSession({
|
|
19746
20252
|
abilities,
|
|
@@ -19910,7 +20416,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19910
20416
|
* `forceWalletSign` is not set.
|
|
19911
20417
|
*/
|
|
19912
20418
|
async delegateTo(did, permissions, options) {
|
|
19913
|
-
const session = this.
|
|
20419
|
+
const session = this.currentTinyCloudSession();
|
|
19914
20420
|
if (!session) {
|
|
19915
20421
|
throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
|
|
19916
20422
|
}
|
|
@@ -20024,11 +20530,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20024
20530
|
* the current session; we build one multi-resource abilities map
|
|
20025
20531
|
* and emit one signed UCAN covering them all.
|
|
20026
20532
|
*
|
|
20027
|
-
*
|
|
20028
|
-
*
|
|
20029
|
-
* spaces in a single delegation is not supported by the underlying
|
|
20030
|
-
* Rust create_delegation call and the resulting UCAN would be
|
|
20031
|
-
* 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.
|
|
20032
20535
|
*
|
|
20033
20536
|
* @internal
|
|
20034
20537
|
*/
|
|
@@ -20040,15 +20543,18 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20040
20543
|
}
|
|
20041
20544
|
const resolvedSpaces = /* @__PURE__ */ new Set();
|
|
20042
20545
|
for (const entry of entries) {
|
|
20546
|
+
if (this.isEncryptionPermissionEntry(entry)) {
|
|
20547
|
+
continue;
|
|
20548
|
+
}
|
|
20043
20549
|
const spaceId2 = this.resolvePermissionSpace(entry.space, session);
|
|
20044
20550
|
resolvedSpaces.add(spaceId2);
|
|
20045
20551
|
}
|
|
20046
|
-
if (resolvedSpaces.size
|
|
20552
|
+
if (resolvedSpaces.size > 1) {
|
|
20047
20553
|
throw new Error(
|
|
20048
20554
|
`delegateTo: all permission entries must target the same space, got ${resolvedSpaces.size}: ${JSON.stringify([...resolvedSpaces])}`
|
|
20049
20555
|
);
|
|
20050
20556
|
}
|
|
20051
|
-
const spaceId = [...resolvedSpaces][0];
|
|
20557
|
+
const spaceId = resolvedSpaces.size === 1 ? [...resolvedSpaces][0] : session.spaceId;
|
|
20052
20558
|
const abilities = {};
|
|
20053
20559
|
for (const entry of entries) {
|
|
20054
20560
|
const shortService = SERVICE_LONG_TO_SHORT[entry.service];
|
|
@@ -20195,11 +20701,32 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20195
20701
|
}
|
|
20196
20702
|
return abilities;
|
|
20197
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
|
+
}
|
|
20198
20725
|
permissionOperations(entries, spaceId) {
|
|
20199
20726
|
return entries.flatMap((entry) => {
|
|
20200
20727
|
const service = this.shortServiceName(entry.service);
|
|
20201
20728
|
return entry.actions.map((action) => ({
|
|
20202
|
-
spaceId,
|
|
20729
|
+
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId },
|
|
20203
20730
|
service,
|
|
20204
20731
|
path: entry.path,
|
|
20205
20732
|
action
|
|
@@ -20222,7 +20749,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20222
20749
|
const spaceId = this.resolvePermissionSpace(entry.space, session);
|
|
20223
20750
|
const service = this.shortServiceName(entry.service);
|
|
20224
20751
|
return entry.actions.map((action) => ({
|
|
20225
|
-
spaceId,
|
|
20752
|
+
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId },
|
|
20226
20753
|
service,
|
|
20227
20754
|
path: entry.path,
|
|
20228
20755
|
action
|
|
@@ -20279,24 +20806,40 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20279
20806
|
expiresAt: delegation.expiry
|
|
20280
20807
|
};
|
|
20281
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
|
+
}
|
|
20282
20824
|
delegatedResourcesForEntries(entries, spaceId) {
|
|
20283
20825
|
return entries.map((entry) => ({
|
|
20284
20826
|
service: this.shortServiceName(entry.service),
|
|
20285
|
-
space: spaceId,
|
|
20827
|
+
space: this.isEncryptionPermissionEntry(entry) ? "encryption" : spaceId,
|
|
20286
20828
|
path: entry.path,
|
|
20287
20829
|
actions: [...entry.actions]
|
|
20288
20830
|
}));
|
|
20289
20831
|
}
|
|
20290
20832
|
operationsFromDelegation(delegation) {
|
|
20291
20833
|
const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
|
|
20292
|
-
return resources.flatMap(
|
|
20293
|
-
|
|
20294
|
-
|
|
20295
|
-
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,
|
|
20296
20839
|
path: resource.path,
|
|
20297
20840
|
action
|
|
20298
|
-
}))
|
|
20299
|
-
);
|
|
20841
|
+
}));
|
|
20842
|
+
});
|
|
20300
20843
|
}
|
|
20301
20844
|
flatDelegationResources(delegation) {
|
|
20302
20845
|
const byService = /* @__PURE__ */ new Map();
|
|
@@ -20345,7 +20888,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20345
20888
|
);
|
|
20346
20889
|
}
|
|
20347
20890
|
operationCovers(granted, requested) {
|
|
20348
|
-
|
|
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);
|
|
20349
20898
|
}
|
|
20350
20899
|
actionContains(grantedAction, requestedAction) {
|
|
20351
20900
|
if (grantedAction === requestedAction) {
|
|
@@ -20360,6 +20909,37 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20360
20909
|
invocationServiceName(service) {
|
|
20361
20910
|
return service.startsWith("tinycloud.") ? this.shortServiceName(service) : service;
|
|
20362
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
|
+
}
|
|
20363
20943
|
pathContains(grantedPath, requestedPath) {
|
|
20364
20944
|
if (grantedPath === "" || grantedPath === "/") {
|
|
20365
20945
|
return true;
|
|
@@ -20598,6 +21178,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20598
21178
|
// Not used in session-only mode
|
|
20599
21179
|
};
|
|
20600
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
|
+
);
|
|
20601
21192
|
return new DelegatedAccess(session2, delegation, targetHost, this.wasmBindings.invoke);
|
|
20602
21193
|
}
|
|
20603
21194
|
const mySession = this.auth?.tinyCloudSession;
|
|
@@ -20609,6 +21200,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20609
21200
|
const kvActions = delegation.actions.filter((a) => a.startsWith("tinycloud.kv/"));
|
|
20610
21201
|
const sqlActions = delegation.actions.filter((a) => a.startsWith("tinycloud.sql/"));
|
|
20611
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 = {};
|
|
20612
21207
|
if (kvActions.length > 0) {
|
|
20613
21208
|
abilities.kv = { [delegation.path]: kvActions };
|
|
20614
21209
|
}
|
|
@@ -20618,6 +21213,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20618
21213
|
if (duckdbActions.length > 0) {
|
|
20619
21214
|
abilities.duckdb = { [delegation.path]: duckdbActions };
|
|
20620
21215
|
}
|
|
21216
|
+
if (encryptionActions.length > 0 && delegation.path.startsWith("urn:tinycloud:encryption:")) {
|
|
21217
|
+
rawAbilities[delegation.path] = encryptionActions;
|
|
21218
|
+
}
|
|
20621
21219
|
const now = /* @__PURE__ */ new Date();
|
|
20622
21220
|
const maxExpiry = new Date(now.getTime() + 60 * 60 * 1e3);
|
|
20623
21221
|
const expirationTime = delegation.expiry < maxExpiry ? delegation.expiry : maxExpiry;
|
|
@@ -20630,7 +21228,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20630
21228
|
expirationTime: expirationTime.toISOString(),
|
|
20631
21229
|
spaceId: delegation.spaceId,
|
|
20632
21230
|
jwk,
|
|
20633
|
-
parents: [delegation.cid]
|
|
21231
|
+
parents: [delegation.cid],
|
|
21232
|
+
...Object.keys(rawAbilities).length > 0 ? { rawAbilities } : {}
|
|
20634
21233
|
});
|
|
20635
21234
|
const signature2 = await this.signer.signMessage(prepared.siwe);
|
|
20636
21235
|
const invokerSession = this.wasmBindings.completeSessionSetup({
|
|
@@ -20657,6 +21256,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20657
21256
|
signature: signature2
|
|
20658
21257
|
};
|
|
20659
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
|
+
);
|
|
20660
21270
|
return new DelegatedAccess(session, delegation, targetHost, this.wasmBindings.invoke);
|
|
20661
21271
|
}
|
|
20662
21272
|
/**
|
|
@@ -20911,7 +21521,7 @@ import {
|
|
|
20911
21521
|
loadManifest,
|
|
20912
21522
|
isCapabilitySubset as isCapabilitySubset2,
|
|
20913
21523
|
expandActionShortNames,
|
|
20914
|
-
expandPermissionEntries,
|
|
21524
|
+
expandPermissionEntries as expandPermissionEntries2,
|
|
20915
21525
|
expandPermissionEntry,
|
|
20916
21526
|
parseExpiry as parseExpiry2,
|
|
20917
21527
|
resourceCapabilitiesToSpaceAbilitiesMap as resourceCapabilitiesToSpaceAbilitiesMap2
|
|
@@ -20934,7 +21544,11 @@ function deserializeDelegation(data) {
|
|
|
20934
21544
|
}
|
|
20935
21545
|
|
|
20936
21546
|
// src/index.ts
|
|
20937
|
-
import {
|
|
21547
|
+
import {
|
|
21548
|
+
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
21549
|
+
KVService as KVService3,
|
|
21550
|
+
PrefixedKVService
|
|
21551
|
+
} from "@tinycloud/sdk-core";
|
|
20938
21552
|
import { SQLService as SQLService3, SQLAction, DatabaseHandle } from "@tinycloud/sdk-core";
|
|
20939
21553
|
import {
|
|
20940
21554
|
DuckDbService as DuckDbService3,
|
|
@@ -20946,7 +21560,53 @@ import {
|
|
|
20946
21560
|
VaultHeaders,
|
|
20947
21561
|
VaultPublicSpaceKVActions,
|
|
20948
21562
|
createVaultCrypto as createVaultCrypto2,
|
|
20949
|
-
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
|
|
20950
21610
|
} from "@tinycloud/sdk-core";
|
|
20951
21611
|
import { HooksService as HooksService3 } from "@tinycloud/sdk-core";
|
|
20952
21612
|
import {
|
|
@@ -20982,8 +21642,14 @@ export {
|
|
|
20982
21642
|
AutoApproveSpaceCreationHandler2 as AutoApproveSpaceCreationHandler,
|
|
20983
21643
|
CapabilityKeyRegistry2 as CapabilityKeyRegistry,
|
|
20984
21644
|
CapabilityKeyRegistryErrorCodes,
|
|
21645
|
+
DECRYPT_ACTION2 as DECRYPT_ACTION,
|
|
21646
|
+
DECRYPT_FACT_TYPE,
|
|
21647
|
+
DECRYPT_RESULT_TYPE,
|
|
21648
|
+
DEFAULT_ENCRYPTION_ALG,
|
|
21649
|
+
DEFAULT_KEY_VERSION,
|
|
20985
21650
|
DEFAULT_MANIFEST_SPACE2 as DEFAULT_MANIFEST_SPACE,
|
|
20986
21651
|
DEFAULT_MANIFEST_VERSION,
|
|
21652
|
+
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
20987
21653
|
DataVaultService2 as DataVaultService,
|
|
20988
21654
|
DatabaseHandle,
|
|
20989
21655
|
DelegatedAccess,
|
|
@@ -20992,17 +21658,25 @@ export {
|
|
|
20992
21658
|
DuckDbAction,
|
|
20993
21659
|
DuckDbDatabaseHandle,
|
|
20994
21660
|
DuckDbService3 as DuckDbService,
|
|
21661
|
+
ENCRYPTION_NETWORK_URN_PREFIX,
|
|
21662
|
+
ENCRYPTION_SERVICE,
|
|
21663
|
+
ENCRYPTION_SERVICE_SHORT,
|
|
21664
|
+
ENVELOPE_VERSION,
|
|
21665
|
+
EncryptionService2 as EncryptionService,
|
|
20995
21666
|
FileSessionStorage,
|
|
20996
21667
|
HooksService3 as HooksService,
|
|
20997
21668
|
KVService3 as KVService,
|
|
20998
21669
|
ManifestValidationError,
|
|
20999
21670
|
MemorySessionStorage,
|
|
21671
|
+
NETWORK_NAME_PATTERN,
|
|
21672
|
+
NetworkIdError,
|
|
21000
21673
|
NodeUserAuthorization,
|
|
21001
21674
|
NodeWasmBindings,
|
|
21002
21675
|
PermissionNotInManifestError2 as PermissionNotInManifestError,
|
|
21003
21676
|
PrefixedKVService,
|
|
21004
21677
|
PrivateKeySigner,
|
|
21005
21678
|
ProtocolMismatchError,
|
|
21679
|
+
SECRET_NAME_RE,
|
|
21006
21680
|
SQLAction,
|
|
21007
21681
|
SQLService3 as SQLService,
|
|
21008
21682
|
SecretsService2 as SecretsService,
|
|
@@ -21021,7 +21695,17 @@ export {
|
|
|
21021
21695
|
VaultPublicSpaceKVActions,
|
|
21022
21696
|
VersionCheckError,
|
|
21023
21697
|
WasmKeyProvider,
|
|
21698
|
+
buildCanonicalDecryptRequest,
|
|
21699
|
+
buildDecryptAttenuation,
|
|
21700
|
+
buildDecryptFacts,
|
|
21701
|
+
buildDecryptInvocation,
|
|
21702
|
+
buildNetworkId,
|
|
21024
21703
|
buildSpaceUri,
|
|
21704
|
+
canonicalHashHex2 as canonicalHashHex,
|
|
21705
|
+
canonicalSignedResponse,
|
|
21706
|
+
canonicalizeEncryptionJson2 as canonicalizeEncryptionJson,
|
|
21707
|
+
canonicalizeSecretScope,
|
|
21708
|
+
checkDecryptInvocationInput,
|
|
21025
21709
|
checkNodeInfo2 as checkNodeInfo,
|
|
21026
21710
|
composeManifestRequest2 as composeManifestRequest,
|
|
21027
21711
|
createCapabilityKeyRegistry,
|
|
@@ -21029,21 +21713,42 @@ export {
|
|
|
21029
21713
|
createSpaceService,
|
|
21030
21714
|
createVaultCrypto2 as createVaultCrypto,
|
|
21031
21715
|
createWasmKeyProvider,
|
|
21716
|
+
decryptEnvelopeWithKey,
|
|
21032
21717
|
defaultSignStrategy,
|
|
21033
21718
|
defaultSpaceCreationHandler,
|
|
21719
|
+
deriveSignedReceiverKey,
|
|
21034
21720
|
deserializeDelegation,
|
|
21721
|
+
discoverNetwork,
|
|
21722
|
+
encryptToNetwork,
|
|
21723
|
+
encryptionBase64Decode,
|
|
21724
|
+
encryptionBase64Encode,
|
|
21725
|
+
encryptionError,
|
|
21726
|
+
encryptionUtf8Decode,
|
|
21727
|
+
encryptionUtf8Encode,
|
|
21728
|
+
ensureNetworkUsableForDecrypt,
|
|
21035
21729
|
expandActionShortNames,
|
|
21036
|
-
expandPermissionEntries,
|
|
21730
|
+
expandPermissionEntries2 as expandPermissionEntries,
|
|
21037
21731
|
expandPermissionEntry,
|
|
21732
|
+
generateRandomReceiverKey,
|
|
21733
|
+
hexDecode,
|
|
21734
|
+
hexEncode,
|
|
21038
21735
|
isCapabilitySubset2 as isCapabilitySubset,
|
|
21736
|
+
isNetworkId,
|
|
21039
21737
|
loadManifest,
|
|
21040
21738
|
makePublicSpaceId2 as makePublicSpaceId,
|
|
21739
|
+
networkDiscoveryKey,
|
|
21740
|
+
openWrappedKey,
|
|
21041
21741
|
parseExpiry2 as parseExpiry,
|
|
21742
|
+
parseNetworkId,
|
|
21042
21743
|
parseSpaceUri,
|
|
21043
21744
|
resolveManifest2 as resolveManifest,
|
|
21745
|
+
resolveSecretListPrefix2 as resolveSecretListPrefix,
|
|
21746
|
+
resolveSecretPath2 as resolveSecretPath,
|
|
21044
21747
|
resourceCapabilitiesToSpaceAbilitiesMap2 as resourceCapabilitiesToSpaceAbilitiesMap,
|
|
21045
21748
|
serializeDelegation,
|
|
21046
|
-
|
|
21749
|
+
validateEnvelope,
|
|
21750
|
+
validateManifest,
|
|
21751
|
+
verifyDecryptResponse
|
|
21047
21752
|
};
|
|
21048
21753
|
/*! Bundled license information:
|
|
21049
21754
|
|