@tinycloud/node-sdk 2.11.0-beta.8 → 2.11.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-Bkptd8qZ.d.cts → core-Bq8TMY7Y.d.cts} +188 -8
- package/dist/{core-Bkptd8qZ.d.ts → core-Bq8TMY7Y.d.ts} +188 -8
- package/dist/core.cjs +675 -67
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +693 -75
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +752 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -3
- package/dist/index.d.ts +85 -3
- package/dist/index.js +765 -76
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -17025,10 +17025,13 @@ var require_utils2 = __commonJS({
|
|
|
17025
17025
|
// src/index.ts
|
|
17026
17026
|
var index_exports = {};
|
|
17027
17027
|
__export(index_exports, {
|
|
17028
|
+
ACCEPTED_MARKER_VERSIONS: () => ACCEPTED_MARKER_VERSIONS,
|
|
17028
17029
|
ACCOUNT_REGISTRY_PATH: () => import_sdk_core12.ACCOUNT_REGISTRY_PATH,
|
|
17029
17030
|
ACCOUNT_REGISTRY_SPACE: () => import_sdk_core12.ACCOUNT_REGISTRY_SPACE,
|
|
17030
17031
|
AccountService: () => import_sdk_core3.AccountService,
|
|
17031
17032
|
AutoApproveSpaceCreationHandler: () => import_sdk_core11.AutoApproveSpaceCreationHandler,
|
|
17033
|
+
BOOTSTRAP_COMPLETION_MARKER_KEY: () => BOOTSTRAP_COMPLETION_MARKER_KEY,
|
|
17034
|
+
BOOTSTRAP_COMPLETION_MARKER_VERSION: () => BOOTSTRAP_COMPLETION_MARKER_VERSION,
|
|
17032
17035
|
CapabilityKeyRegistry: () => import_sdk_core20.CapabilityKeyRegistry,
|
|
17033
17036
|
CapabilityKeyRegistryErrorCodes: () => import_sdk_core20.CapabilityKeyRegistryErrorCodes,
|
|
17034
17037
|
CaveatedDelegationUnsupportedError: () => import_sdk_core12.CaveatedDelegationUnsupportedError,
|
|
@@ -17165,7 +17168,8 @@ __export(index_exports, {
|
|
|
17165
17168
|
tinyCloudDebugLogger: () => import_sdk_core11.tinyCloudDebugLogger,
|
|
17166
17169
|
validateEnvelope: () => import_sdk_core17.validateEnvelope,
|
|
17167
17170
|
validateManifest: () => import_sdk_core12.validateManifest,
|
|
17168
|
-
verifyDecryptResponse: () => import_sdk_core17.verifyDecryptResponse
|
|
17171
|
+
verifyDecryptResponse: () => import_sdk_core17.verifyDecryptResponse,
|
|
17172
|
+
wireOpenKeyAuthorize: () => wireOpenKeyAuthorize
|
|
17169
17173
|
});
|
|
17170
17174
|
module.exports = __toCommonJS(index_exports);
|
|
17171
17175
|
|
|
@@ -17278,6 +17282,8 @@ var import_sdk_core7 = require("@tinycloud/sdk-core");
|
|
|
17278
17282
|
var import_sdk_services = require("@tinycloud/sdk-services");
|
|
17279
17283
|
|
|
17280
17284
|
// src/authorization/NodeUserAuthorization.ts
|
|
17285
|
+
var import_node_crypto = require("crypto");
|
|
17286
|
+
var import_siwe = require("siwe");
|
|
17281
17287
|
var import_sdk_core2 = require("@tinycloud/sdk-core");
|
|
17282
17288
|
|
|
17283
17289
|
// src/authorization/strategies.ts
|
|
@@ -17358,6 +17364,27 @@ var MemorySessionStorage = class {
|
|
|
17358
17364
|
// src/authorization/NodeUserAuthorization.ts
|
|
17359
17365
|
var DECRYPT_ACTION = import_sdk_core2.ENCRYPTION.DECRYPT;
|
|
17360
17366
|
var NETWORK_CREATE_ACTION = import_sdk_core2.ENCRYPTION.NETWORK_CREATE;
|
|
17367
|
+
function canonicalizeOpenKeyManifestJson(value) {
|
|
17368
|
+
const json = JSON.stringify(value);
|
|
17369
|
+
if (json === void 0) {
|
|
17370
|
+
throw new TypeError("manifest is not JSON-serializable");
|
|
17371
|
+
}
|
|
17372
|
+
return canonicalizeJsonValue(JSON.parse(json));
|
|
17373
|
+
}
|
|
17374
|
+
function canonicalizeJsonValue(value) {
|
|
17375
|
+
if (value === null || typeof value !== "object") {
|
|
17376
|
+
return JSON.stringify(value);
|
|
17377
|
+
}
|
|
17378
|
+
if (Array.isArray(value)) {
|
|
17379
|
+
return `[${value.map(canonicalizeJsonValue).join(",")}]`;
|
|
17380
|
+
}
|
|
17381
|
+
return `{${Object.keys(value).sort().map(
|
|
17382
|
+
(key2) => `${JSON.stringify(key2)}:${canonicalizeJsonValue(value[key2])}`
|
|
17383
|
+
).join(",")}}`;
|
|
17384
|
+
}
|
|
17385
|
+
function canonicalOpenKeyManifestSha256Hex(value) {
|
|
17386
|
+
return (0, import_node_crypto.createHash)("sha256").update(canonicalizeOpenKeyManifestJson(value)).digest("hex");
|
|
17387
|
+
}
|
|
17361
17388
|
function didPrincipalMatches(actual, expected) {
|
|
17362
17389
|
try {
|
|
17363
17390
|
return (0, import_sdk_core2.principalDidEquals)(actual, expected);
|
|
@@ -17375,6 +17402,16 @@ function addRawAbility(rawAbilities, resource, action) {
|
|
|
17375
17402
|
actions.push(action);
|
|
17376
17403
|
}
|
|
17377
17404
|
}
|
|
17405
|
+
function cloneAbilitiesMap(actions) {
|
|
17406
|
+
return Object.fromEntries(
|
|
17407
|
+
Object.entries(actions).map(([service, paths]) => [
|
|
17408
|
+
service,
|
|
17409
|
+
Object.fromEntries(
|
|
17410
|
+
Object.entries(paths).map(([path, pathActions]) => [path, [...pathActions]])
|
|
17411
|
+
)
|
|
17412
|
+
])
|
|
17413
|
+
);
|
|
17414
|
+
}
|
|
17378
17415
|
var NodeUserAuthorization = class {
|
|
17379
17416
|
constructor(config) {
|
|
17380
17417
|
this.activeSessionKeyId = "default";
|
|
@@ -17646,23 +17683,41 @@ var NodeUserAuthorization = class {
|
|
|
17646
17683
|
const defaultNetworkId = this.defaultEncryptionNetworkId(address, chainId);
|
|
17647
17684
|
const primarySpaceId2 = (0, import_sdk_core2.makePkhSpaceId)(address, chainId, this.spacePrefix);
|
|
17648
17685
|
const secretsSpaceId = (0, import_sdk_core2.makePkhSpaceId)(address, chainId, "secrets");
|
|
17649
|
-
|
|
17650
|
-
|
|
17651
|
-
|
|
17652
|
-
|
|
17653
|
-
|
|
17654
|
-
|
|
17655
|
-
|
|
17656
|
-
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17661
|
-
|
|
17662
|
-
|
|
17686
|
+
const primaryActions = this.includeAccountRegistryPermissions && this.spacePrefix === import_sdk_core2.ACCOUNT_REGISTRY_SPACE ? cloneAbilitiesMap(this.defaultActions) : this.defaultActions;
|
|
17687
|
+
const spaceAbilities2 = {
|
|
17688
|
+
[primarySpaceId2]: primaryActions,
|
|
17689
|
+
[secretsSpaceId]: {
|
|
17690
|
+
kv: {
|
|
17691
|
+
"vault/secrets/": [
|
|
17692
|
+
import_sdk_core2.KV.GET,
|
|
17693
|
+
import_sdk_core2.KV.PUT,
|
|
17694
|
+
import_sdk_core2.KV.DEL,
|
|
17695
|
+
import_sdk_core2.KV.LIST,
|
|
17696
|
+
import_sdk_core2.KV.METADATA
|
|
17697
|
+
]
|
|
17698
|
+
}
|
|
17699
|
+
}
|
|
17700
|
+
};
|
|
17701
|
+
if (this.includeAccountRegistryPermissions && this.spacePrefix !== import_sdk_core2.ACCOUNT_REGISTRY_SPACE) {
|
|
17702
|
+
spaceAbilities2[(0, import_sdk_core2.makePkhSpaceId)(address, chainId, import_sdk_core2.ACCOUNT_REGISTRY_SPACE)] = (0, import_sdk_core2.resourceCapabilitiesToAbilitiesMap)(import_sdk_core2.ACCOUNT_MANIFEST_PERMISSIONS);
|
|
17703
|
+
} else if (this.includeAccountRegistryPermissions) {
|
|
17704
|
+
const accountAbilities = (0, import_sdk_core2.resourceCapabilitiesToAbilitiesMap)(
|
|
17705
|
+
import_sdk_core2.ACCOUNT_MANIFEST_PERMISSIONS
|
|
17706
|
+
);
|
|
17707
|
+
for (const [service, paths] of Object.entries(accountAbilities)) {
|
|
17708
|
+
const existingPaths = primaryActions[service] ?? (primaryActions[service] = {});
|
|
17709
|
+
for (const [path, actions] of Object.entries(paths)) {
|
|
17710
|
+
const existingActions = existingPaths[path] ?? (existingPaths[path] = []);
|
|
17711
|
+
for (const action of actions) {
|
|
17712
|
+
if (!existingActions.includes(action)) existingActions.push(action);
|
|
17663
17713
|
}
|
|
17664
17714
|
}
|
|
17665
|
-
}
|
|
17715
|
+
}
|
|
17716
|
+
}
|
|
17717
|
+
return {
|
|
17718
|
+
abilities: primaryActions,
|
|
17719
|
+
spaceId: primarySpaceId2,
|
|
17720
|
+
spaceAbilities: spaceAbilities2,
|
|
17666
17721
|
rawAbilities: {
|
|
17667
17722
|
[defaultNetworkId]: [DECRYPT_ACTION, NETWORK_CREATE_ACTION]
|
|
17668
17723
|
}
|
|
@@ -18243,6 +18298,398 @@ var NodeUserAuthorization = class {
|
|
|
18243
18298
|
await this.ensureSpaceExists();
|
|
18244
18299
|
return clientSession;
|
|
18245
18300
|
}
|
|
18301
|
+
/**
|
|
18302
|
+
* End-to-end sign-in via OpenKey `authorizeTinyCloud()` (Sol CRITICAL-4).
|
|
18303
|
+
*
|
|
18304
|
+
* This is the production entry point that wires
|
|
18305
|
+
* {@link prepareSessionForSigning} → OpenKey `authorizeTinyCloud()` →
|
|
18306
|
+
* {@link signInWithOpenKeyResult} into one call. Consumers pass in a
|
|
18307
|
+
* caller-provided `authorizeFn` (typically a thin wrapper around
|
|
18308
|
+
* `openkey.authorizeTinyCloud()`) so this method has no direct
|
|
18309
|
+
* dependency on the OpenKey SDK — it works with any transport that
|
|
18310
|
+
* conforms to the versioned protocol.
|
|
18311
|
+
*
|
|
18312
|
+
* The `authorizeFn` MUST:
|
|
18313
|
+
* 1. Send the prepared SIWE bytes to OpenKey.
|
|
18314
|
+
* 2. Return the exact `TinyCloudAuthorizationResultV1` shape (with
|
|
18315
|
+
* `signedMessage` — the bytes the signature actually verifies
|
|
18316
|
+
* against — plus `selectedActionKeys` and `permissions`).
|
|
18317
|
+
*
|
|
18318
|
+
* NodeUserAuthorization then completes the session with `signedMessage`
|
|
18319
|
+
* (never the prepared bytes), verifying the signature, the immutable
|
|
18320
|
+
* SIWE fields, and every subset invariant enforced by
|
|
18321
|
+
* {@link signInWithOpenKeyResult}. This preserves the exact-byte
|
|
18322
|
+
* guarantee: if the user did NOT narrow, the returned `signedMessage`
|
|
18323
|
+
* equals the prepared SIWE byte-for-byte; if the user narrowed, only
|
|
18324
|
+
* the ReCap block differs and every immutable header field survives.
|
|
18325
|
+
*
|
|
18326
|
+
* Legacy exact-byte {@link signIn} callers are unaffected — this method
|
|
18327
|
+
* is opt-in.
|
|
18328
|
+
*
|
|
18329
|
+
* @param authorizeFn Callback that invokes the versioned OpenKey
|
|
18330
|
+
* `authorizeTinyCloud()` protocol and returns the result. Receives
|
|
18331
|
+
* the prepared SIWE bytes plus a `host` hint the widget should bind
|
|
18332
|
+
* into its /authorize-sign-prepare context.
|
|
18333
|
+
* @param options Optional overrides for the OpenKey request.
|
|
18334
|
+
*/
|
|
18335
|
+
async signInWithOpenKey(authorizeFn, options) {
|
|
18336
|
+
if (options?.host !== void 0) {
|
|
18337
|
+
const overrideHost = options.host.trim();
|
|
18338
|
+
if (!overrideHost) {
|
|
18339
|
+
throw new Error("OpenKey authorization host must not be empty");
|
|
18340
|
+
}
|
|
18341
|
+
this.tinycloudHosts = [overrideHost];
|
|
18342
|
+
}
|
|
18343
|
+
const signingAddress = (0, import_sdk_core2.canonicalizeAddress)(await this.signer.getAddress());
|
|
18344
|
+
const signingChainId = await this.signer.getChainId();
|
|
18345
|
+
await this.resolveTinyCloudHostsForSignIn(signingAddress, signingChainId);
|
|
18346
|
+
const { prepared, keyId, jwk } = await this.prepareSessionForSigning();
|
|
18347
|
+
const presentation = this.buildPresentationEnvelope(options?.reason);
|
|
18348
|
+
const hostHint = this.primaryTinyCloudHost;
|
|
18349
|
+
const result = await authorizeFn({
|
|
18350
|
+
protocolVersion: 1,
|
|
18351
|
+
siwe: prepared.siwe,
|
|
18352
|
+
jwk,
|
|
18353
|
+
host: hostHint,
|
|
18354
|
+
keyId: options?.openkeyKeyId,
|
|
18355
|
+
presentation
|
|
18356
|
+
});
|
|
18357
|
+
return this.signInWithOpenKeyResult(result, prepared, keyId, jwk);
|
|
18358
|
+
}
|
|
18359
|
+
/**
|
|
18360
|
+
* Build a `CapabilityPresentationEnvelopeV1` from `this._manifest`. The
|
|
18361
|
+
* envelope is display-only — the OpenKey widget renders it under an
|
|
18362
|
+
* honest trust label, and the server /authorize-sign-prepare route
|
|
18363
|
+
* decides whether to upgrade the label to `origin-bound` by fetching
|
|
18364
|
+
* the well-known manifest and comparing its digest to
|
|
18365
|
+
* `manifestDigest`.
|
|
18366
|
+
*
|
|
18367
|
+
* Returns `undefined` when no manifest is set — the widget renders as
|
|
18368
|
+
* "no manifest supplied" (unsigned).
|
|
18369
|
+
*
|
|
18370
|
+
* The digest is a deterministic SHA-256 over canonical JSON of the
|
|
18371
|
+
* first manifest payload; OpenKey parses the fetched well-known manifest
|
|
18372
|
+
* and applies the same canonicalization before comparing digests.
|
|
18373
|
+
*/
|
|
18374
|
+
buildPresentationEnvelope(reason) {
|
|
18375
|
+
const manifests = Array.isArray(this._manifest) ? this._manifest : this._manifest ? [this._manifest] : [];
|
|
18376
|
+
if (manifests.length === 0 && !reason) {
|
|
18377
|
+
return void 0;
|
|
18378
|
+
}
|
|
18379
|
+
const primary = manifests[0];
|
|
18380
|
+
let displayName;
|
|
18381
|
+
let manifestId;
|
|
18382
|
+
let manifestDigest;
|
|
18383
|
+
const envelopeManifests = [];
|
|
18384
|
+
for (const m of manifests) {
|
|
18385
|
+
envelopeManifests.push({
|
|
18386
|
+
name: m.name,
|
|
18387
|
+
appId: m.app_id,
|
|
18388
|
+
// Deep-copy to prevent later mutations from affecting the digest.
|
|
18389
|
+
payload: JSON.parse(JSON.stringify(m))
|
|
18390
|
+
});
|
|
18391
|
+
}
|
|
18392
|
+
if (primary) {
|
|
18393
|
+
displayName = primary.name;
|
|
18394
|
+
manifestId = primary.app_id;
|
|
18395
|
+
manifestDigest = canonicalOpenKeyManifestSha256Hex(primary);
|
|
18396
|
+
}
|
|
18397
|
+
return {
|
|
18398
|
+
protocolVersion: 1,
|
|
18399
|
+
displayName,
|
|
18400
|
+
reason: reason && reason.length > 0 ? reason : void 0,
|
|
18401
|
+
manifestId,
|
|
18402
|
+
manifestDigest,
|
|
18403
|
+
manifests: envelopeManifests.length > 0 ? envelopeManifests : void 0
|
|
18404
|
+
};
|
|
18405
|
+
}
|
|
18406
|
+
/**
|
|
18407
|
+
* Complete sign-in with a versioned OpenKey authorization result.
|
|
18408
|
+
*
|
|
18409
|
+
* Where `signInWithPreparedSession` completes with a signature over the
|
|
18410
|
+
* ORIGINAL prepared SIWE, this method completes with the SIWE bytes the
|
|
18411
|
+
* OpenKey widget actually presented and signed (`signedMessage`). It
|
|
18412
|
+
* exists because the versioned authorizeTinyCloud protocol lets the user
|
|
18413
|
+
* narrow capabilities; the returned bytes may differ from the original
|
|
18414
|
+
* request and are the only ones the signature actually verifies against.
|
|
18415
|
+
*
|
|
18416
|
+
* The `result` parameter is validated at the trust boundary via
|
|
18417
|
+
* `validateAuthorizationResultV1` (in sdk-core). Callers should validate
|
|
18418
|
+
* BEFORE calling this method so unknown/missing fields are rejected
|
|
18419
|
+
* before any session state is created.
|
|
18420
|
+
*
|
|
18421
|
+
* Validation performed here (defence-in-depth: even a "valid" v1 payload
|
|
18422
|
+
* must clear these checks before any session state is created):
|
|
18423
|
+
* 1. `result.address` matches the local signer's address.
|
|
18424
|
+
* 2. `result.signature` recovers to `result.address` when verified against
|
|
18425
|
+
* `result.signedMessage`.
|
|
18426
|
+
* 3. Every immutable SIWE header field (domain, address, URI, version,
|
|
18427
|
+
* chainId, nonce, issuedAt) in the original prepared SIWE is preserved
|
|
18428
|
+
* byte-for-byte in `result.signedMessage`. `statement` is NOT in this
|
|
18429
|
+
* list because the WASM renders it from the ReCap contents; it MUST
|
|
18430
|
+
* change when the ReCap is narrowed.
|
|
18431
|
+
* 4. Every capability in `result.signedMessage`'s ReCap block was present
|
|
18432
|
+
* in the original prepared SIWE — narrowing OK, broadening rejected.
|
|
18433
|
+
* 5. Every `result.selectedActionKeys` entry corresponds to a
|
|
18434
|
+
* (resource, action) pair in the returned SIWE.
|
|
18435
|
+
*/
|
|
18436
|
+
async signInWithOpenKeyResult(result, prepared, keyId, jwk) {
|
|
18437
|
+
if (result.protocolVersion !== 1) {
|
|
18438
|
+
throw new Error(`Unsupported OpenKey protocol version ${result.protocolVersion}`);
|
|
18439
|
+
}
|
|
18440
|
+
if (!result.signedMessage) {
|
|
18441
|
+
throw new Error("OpenKey result must include signedMessage");
|
|
18442
|
+
}
|
|
18443
|
+
if (!prepared.siwe) {
|
|
18444
|
+
throw new Error(
|
|
18445
|
+
"signInWithOpenKeyResult requires prepared.siwe (the SDK-generated SIWE the sign-in was proposed with)"
|
|
18446
|
+
);
|
|
18447
|
+
}
|
|
18448
|
+
const expectedAddress = (0, import_sdk_core2.canonicalizeAddress)(await this.signer.getAddress());
|
|
18449
|
+
if ((0, import_sdk_core2.canonicalizeAddress)(result.address) !== expectedAddress) {
|
|
18450
|
+
throw new Error(
|
|
18451
|
+
`OpenKey returned signature from ${result.address} but expected ${expectedAddress}`
|
|
18452
|
+
);
|
|
18453
|
+
}
|
|
18454
|
+
let parsedSignedSiwe;
|
|
18455
|
+
try {
|
|
18456
|
+
parsedSignedSiwe = new import_siwe.SiweMessage(result.signedMessage);
|
|
18457
|
+
} catch (err) {
|
|
18458
|
+
throw new Error(
|
|
18459
|
+
`OpenKey signedMessage is not a parseable SIWE: ${err.message}`
|
|
18460
|
+
);
|
|
18461
|
+
}
|
|
18462
|
+
const verifyResult = await parsedSignedSiwe.verify(
|
|
18463
|
+
{ signature: result.signature },
|
|
18464
|
+
{ suppressExceptions: true }
|
|
18465
|
+
);
|
|
18466
|
+
if (!verifyResult.success) {
|
|
18467
|
+
const errData = verifyResult.error;
|
|
18468
|
+
const type = errData && typeof errData === "object" && "type" in errData ? errData.type : void 0;
|
|
18469
|
+
const details = errData && typeof errData === "object" && "expected" in errData ? ` (expected=${errData.expected}, received=${errData.received})` : "";
|
|
18470
|
+
throw new Error(
|
|
18471
|
+
`OpenKey signature verification failed${type ? `: ${type}` : ""}${details}`
|
|
18472
|
+
);
|
|
18473
|
+
}
|
|
18474
|
+
if ((0, import_sdk_core2.canonicalizeAddress)(parsedSignedSiwe.address) !== expectedAddress) {
|
|
18475
|
+
throw new Error(
|
|
18476
|
+
`OpenKey signedMessage.address (${parsedSignedSiwe.address}) does not match local signer address (${expectedAddress})`
|
|
18477
|
+
);
|
|
18478
|
+
}
|
|
18479
|
+
const originalHasRecap = /(?:^|\n)-\s+urn:recap:/i.test(prepared.siwe);
|
|
18480
|
+
const originalFields = (0, import_sdk_core2.extractImmutableSiweFields)(prepared.siwe);
|
|
18481
|
+
const signedFields = (0, import_sdk_core2.extractImmutableSiweFields)(result.signedMessage);
|
|
18482
|
+
const changedFields = (0, import_sdk_core2.diffImmutableSiweFields)(originalFields, signedFields, {
|
|
18483
|
+
originalHasRecap
|
|
18484
|
+
});
|
|
18485
|
+
if (changedFields.length > 0) {
|
|
18486
|
+
throw new Error(
|
|
18487
|
+
`OpenKey signedMessage altered immutable SIWE fields: ${changedFields.join(", ")}`
|
|
18488
|
+
);
|
|
18489
|
+
}
|
|
18490
|
+
let originalCaps;
|
|
18491
|
+
let signedCaps;
|
|
18492
|
+
try {
|
|
18493
|
+
originalCaps = (0, import_sdk_core2.extractRecapAttenuations)(prepared.siwe);
|
|
18494
|
+
} catch (err) {
|
|
18495
|
+
throw new Error(
|
|
18496
|
+
`Failed to decode prepared SIWE recap: ${err.message}`
|
|
18497
|
+
);
|
|
18498
|
+
}
|
|
18499
|
+
try {
|
|
18500
|
+
signedCaps = (0, import_sdk_core2.extractRecapAttenuations)(result.signedMessage);
|
|
18501
|
+
} catch (err) {
|
|
18502
|
+
throw new Error(
|
|
18503
|
+
`Failed to decode OpenKey signedMessage recap: ${err.message}`
|
|
18504
|
+
);
|
|
18505
|
+
}
|
|
18506
|
+
const unauthorized = (0, import_sdk_core2.unauthorizedRecapCapabilities)(signedCaps, originalCaps);
|
|
18507
|
+
if (unauthorized.length > 0) {
|
|
18508
|
+
const previewLimit = 5;
|
|
18509
|
+
const preview = unauthorized.slice(0, previewLimit).map((u) => `${u.resource}::${u.action}`).join(", ");
|
|
18510
|
+
const overflow = unauthorized.length > previewLimit ? ` (and ${unauthorized.length - previewLimit} more)` : "";
|
|
18511
|
+
throw new Error(
|
|
18512
|
+
`OpenKey signedMessage broadened authorization beyond the original request: ${preview}${overflow}`
|
|
18513
|
+
);
|
|
18514
|
+
}
|
|
18515
|
+
if (!result.signedMessage.includes(prepared.spaceId)) {
|
|
18516
|
+
throw new Error(
|
|
18517
|
+
`OpenKey signedMessage does not reference the expected spaceId ${prepared.spaceId}`
|
|
18518
|
+
);
|
|
18519
|
+
}
|
|
18520
|
+
const grantedPairs = /* @__PURE__ */ new Set();
|
|
18521
|
+
const grantedFourPartIndex = /* @__PURE__ */ new Map();
|
|
18522
|
+
for (const [resource, actions] of Object.entries(signedCaps)) {
|
|
18523
|
+
const { space, path } = (0, import_sdk_core2.parseCanonicalRecapResource)(resource);
|
|
18524
|
+
for (const action of Object.keys(actions)) {
|
|
18525
|
+
grantedPairs.add(`${resource}\0${action}`);
|
|
18526
|
+
const slashIdx = action.indexOf("/");
|
|
18527
|
+
const service = slashIdx > 0 ? action.slice(0, slashIdx) : "";
|
|
18528
|
+
if (service) {
|
|
18529
|
+
grantedFourPartIndex.set(
|
|
18530
|
+
`${service}\0${space}\0${path}\0${action}`,
|
|
18531
|
+
`${resource}\0${action}`
|
|
18532
|
+
);
|
|
18533
|
+
}
|
|
18534
|
+
}
|
|
18535
|
+
}
|
|
18536
|
+
const isStructurallyRequired = (action) => action === "tinycloud.capabilities/read" || action === "capabilities/read";
|
|
18537
|
+
const nonRequiredGrantedPairs = /* @__PURE__ */ new Set();
|
|
18538
|
+
for (const pair of grantedPairs) {
|
|
18539
|
+
const idx = pair.indexOf("\0");
|
|
18540
|
+
const action = idx >= 0 ? pair.slice(idx + 1) : pair;
|
|
18541
|
+
if (!isStructurallyRequired(action)) {
|
|
18542
|
+
nonRequiredGrantedPairs.add(pair);
|
|
18543
|
+
}
|
|
18544
|
+
}
|
|
18545
|
+
const allSignedGrantedPairs = new Set(grantedPairs);
|
|
18546
|
+
const seenRawKeys = /* @__PURE__ */ new Set();
|
|
18547
|
+
for (const rawKey of result.selectedActionKeys) {
|
|
18548
|
+
if (seenRawKeys.has(rawKey)) {
|
|
18549
|
+
throw new Error(
|
|
18550
|
+
`OpenKey selectedActionKeys contains duplicate entry ${rawKey}`
|
|
18551
|
+
);
|
|
18552
|
+
}
|
|
18553
|
+
seenRawKeys.add(rawKey);
|
|
18554
|
+
}
|
|
18555
|
+
const selectedResourceActionPairs = /* @__PURE__ */ new Set();
|
|
18556
|
+
for (const rawKey of result.selectedActionKeys) {
|
|
18557
|
+
const parts = rawKey.split("\0");
|
|
18558
|
+
if (parts.length !== 4) {
|
|
18559
|
+
throw new Error(
|
|
18560
|
+
`OpenKey selectedActionKeys entry is malformed (expected canonical 4-part service\\0space\\0path\\0ability): ${rawKey}`
|
|
18561
|
+
);
|
|
18562
|
+
}
|
|
18563
|
+
const canonical = grantedFourPartIndex.get(rawKey);
|
|
18564
|
+
if (!canonical) {
|
|
18565
|
+
throw new Error(
|
|
18566
|
+
`OpenKey selectedActionKeys entry ${rawKey} is not covered by any granted capability`
|
|
18567
|
+
);
|
|
18568
|
+
}
|
|
18569
|
+
selectedResourceActionPairs.add(canonical);
|
|
18570
|
+
}
|
|
18571
|
+
if (nonRequiredGrantedPairs.size > 0) {
|
|
18572
|
+
const missingPairs = [];
|
|
18573
|
+
for (const pair of nonRequiredGrantedPairs) {
|
|
18574
|
+
if (!selectedResourceActionPairs.has(pair)) {
|
|
18575
|
+
missingPairs.push(pair);
|
|
18576
|
+
}
|
|
18577
|
+
}
|
|
18578
|
+
if (missingPairs.length > 0) {
|
|
18579
|
+
const previewLimit = 5;
|
|
18580
|
+
const preview = missingPairs.slice(0, previewLimit).map((p) => p.replace("\0", "::")).join(", ");
|
|
18581
|
+
const overflow = missingPairs.length > previewLimit ? ` (and ${missingPairs.length - previewLimit} more)` : "";
|
|
18582
|
+
throw new Error(
|
|
18583
|
+
`OpenKey selectedActionKeys is missing entries for signedMessage capabilities: ${preview}${overflow}`
|
|
18584
|
+
);
|
|
18585
|
+
}
|
|
18586
|
+
}
|
|
18587
|
+
if (allSignedGrantedPairs.size > 0 && result.permissions.length === 0) {
|
|
18588
|
+
throw new Error(
|
|
18589
|
+
"OpenKey permissions is empty but signedMessage carries capabilities \u2014 refusing to accept a session without an authoritative grant list"
|
|
18590
|
+
);
|
|
18591
|
+
}
|
|
18592
|
+
const permissionCanonicalKeys = /* @__PURE__ */ new Set();
|
|
18593
|
+
const permissionPairsCovered = /* @__PURE__ */ new Set();
|
|
18594
|
+
for (const perm of result.permissions) {
|
|
18595
|
+
const { service, space, path, actions } = perm;
|
|
18596
|
+
if (typeof service !== "string" || typeof space !== "string" || typeof path !== "string") {
|
|
18597
|
+
throw new Error(
|
|
18598
|
+
`OpenKey permissions entry has non-string service/space/path (service=${service}, space=${space}, path=${path})`
|
|
18599
|
+
);
|
|
18600
|
+
}
|
|
18601
|
+
if (!Array.isArray(actions) || actions.length === 0) {
|
|
18602
|
+
throw new Error(
|
|
18603
|
+
`OpenKey permissions entry (${service} ${space} ${path}) has empty actions \u2014 a capability-bearing entry must list at least one action`
|
|
18604
|
+
);
|
|
18605
|
+
}
|
|
18606
|
+
const canonicalKey = `${service}\0${space}\0${path}`;
|
|
18607
|
+
if (permissionCanonicalKeys.has(canonicalKey)) {
|
|
18608
|
+
throw new Error(
|
|
18609
|
+
`OpenKey permissions has duplicate entry for (${service} ${space} ${path})`
|
|
18610
|
+
);
|
|
18611
|
+
}
|
|
18612
|
+
permissionCanonicalKeys.add(canonicalKey);
|
|
18613
|
+
let expectedResource;
|
|
18614
|
+
if (space.startsWith("tinycloud:")) {
|
|
18615
|
+
const shortService = service.startsWith("tinycloud.") ? service.slice("tinycloud.".length) : service;
|
|
18616
|
+
expectedResource = path ? `${space}/${shortService}/${path}` : `${space}/${shortService}`;
|
|
18617
|
+
} else {
|
|
18618
|
+
if (path) {
|
|
18619
|
+
throw new Error(
|
|
18620
|
+
`OpenKey permissions entry (${service} ${space} ${path}) carries a path on a non-tinycloud: resource URI, which is not a recognized encoding`
|
|
18621
|
+
);
|
|
18622
|
+
}
|
|
18623
|
+
expectedResource = space;
|
|
18624
|
+
}
|
|
18625
|
+
let matchedResource;
|
|
18626
|
+
if (signedCaps[expectedResource] !== void 0) {
|
|
18627
|
+
matchedResource = expectedResource;
|
|
18628
|
+
} else {
|
|
18629
|
+
throw new Error(
|
|
18630
|
+
`OpenKey permissions entry (${service} ${space} ${path}) claims grants not confirmed in signedMessage capabilities`
|
|
18631
|
+
);
|
|
18632
|
+
}
|
|
18633
|
+
const grantedActionsForResource = new Set(
|
|
18634
|
+
Object.keys(signedCaps[matchedResource])
|
|
18635
|
+
);
|
|
18636
|
+
for (const action of actions) {
|
|
18637
|
+
if (typeof action !== "string" || !action) {
|
|
18638
|
+
throw new Error(
|
|
18639
|
+
`OpenKey permissions entry (${service} ${space} ${path}) has non-string action ${String(action)}`
|
|
18640
|
+
);
|
|
18641
|
+
}
|
|
18642
|
+
if (!grantedActionsForResource.has(action)) {
|
|
18643
|
+
throw new Error(
|
|
18644
|
+
`OpenKey permissions entry (${service} ${space} ${path}) claims action ${action} not present in signedMessage capabilities`
|
|
18645
|
+
);
|
|
18646
|
+
}
|
|
18647
|
+
permissionPairsCovered.add(`${matchedResource}\0${action}`);
|
|
18648
|
+
}
|
|
18649
|
+
}
|
|
18650
|
+
if (allSignedGrantedPairs.size > 0) {
|
|
18651
|
+
const missingFromPerms = [];
|
|
18652
|
+
for (const pair of allSignedGrantedPairs) {
|
|
18653
|
+
if (!permissionPairsCovered.has(pair)) {
|
|
18654
|
+
missingFromPerms.push(pair);
|
|
18655
|
+
}
|
|
18656
|
+
}
|
|
18657
|
+
if (missingFromPerms.length > 0) {
|
|
18658
|
+
const previewLimit = 5;
|
|
18659
|
+
const preview = missingFromPerms.slice(0, previewLimit).map((p) => p.replace("\0", "::")).join(", ");
|
|
18660
|
+
const overflow = missingFromPerms.length > previewLimit ? ` (and ${missingFromPerms.length - previewLimit} more)` : "";
|
|
18661
|
+
throw new Error(
|
|
18662
|
+
`OpenKey permissions is missing entries for signedMessage capabilities: ${preview}${overflow}`
|
|
18663
|
+
);
|
|
18664
|
+
}
|
|
18665
|
+
const extrasInPerms = [];
|
|
18666
|
+
for (const pair of permissionPairsCovered) {
|
|
18667
|
+
if (!allSignedGrantedPairs.has(pair)) {
|
|
18668
|
+
extrasInPerms.push(pair);
|
|
18669
|
+
}
|
|
18670
|
+
}
|
|
18671
|
+
if (extrasInPerms.length > 0) {
|
|
18672
|
+
const previewLimit = 5;
|
|
18673
|
+
const preview = extrasInPerms.slice(0, previewLimit).map((p) => p.replace("\0", "::")).join(", ");
|
|
18674
|
+
const overflow = extrasInPerms.length > previewLimit ? ` (and ${extrasInPerms.length - previewLimit} more)` : "";
|
|
18675
|
+
throw new Error(
|
|
18676
|
+
`OpenKey permissions contains entries not present in the signed authority: ${preview}${overflow}`
|
|
18677
|
+
);
|
|
18678
|
+
}
|
|
18679
|
+
}
|
|
18680
|
+
void nonRequiredGrantedPairs;
|
|
18681
|
+
return this.signInWithPreparedSession(
|
|
18682
|
+
{
|
|
18683
|
+
siwe: result.signedMessage,
|
|
18684
|
+
jwk: prepared.jwk,
|
|
18685
|
+
spaceId: prepared.spaceId,
|
|
18686
|
+
verificationMethod: prepared.verificationMethod
|
|
18687
|
+
},
|
|
18688
|
+
result.signature,
|
|
18689
|
+
keyId,
|
|
18690
|
+
jwk
|
|
18691
|
+
);
|
|
18692
|
+
}
|
|
18246
18693
|
/**
|
|
18247
18694
|
* Clear persisted session data.
|
|
18248
18695
|
*/
|
|
@@ -18733,6 +19180,9 @@ var DEFAULT_HOST = "https://node.tinycloud.xyz";
|
|
|
18733
19180
|
var DEFAULT_ENCRYPTION_NETWORK_NAME = "default";
|
|
18734
19181
|
var NETWORK_CREATE_ACTION2 = import_sdk_core7.ENCRYPTION.NETWORK_CREATE;
|
|
18735
19182
|
var DECRYPT_ACTION2 = import_sdk_core7.ENCRYPTION.DECRYPT;
|
|
19183
|
+
var BOOTSTRAP_COMPLETION_MARKER_KEY = "system/bootstrap/complete";
|
|
19184
|
+
var BOOTSTRAP_COMPLETION_MARKER_VERSION = 1;
|
|
19185
|
+
var ACCEPTED_MARKER_VERSIONS = [BOOTSTRAP_COMPLETION_MARKER_VERSION];
|
|
18736
19186
|
var NETWORK_ADMIN_TYPE = "tinycloud.encryption.network-admin/v1";
|
|
18737
19187
|
function isSecretPayload(value) {
|
|
18738
19188
|
return typeof value === "object" && value !== null && "value" in value && typeof value.value === "string" && "createdAt" in value && typeof value.createdAt === "string" && "updatedAt" in value && typeof value.updatedAt === "string";
|
|
@@ -18775,6 +19225,9 @@ function decodeAuthorizationBytes(authorization) {
|
|
|
18775
19225
|
function isOpenKeyAutoSignStrategy(strategy) {
|
|
18776
19226
|
return strategy?.openKeyAutoSign === true;
|
|
18777
19227
|
}
|
|
19228
|
+
function openKeyApproval(strategy) {
|
|
19229
|
+
return strategy?.openKeyRequestApproval;
|
|
19230
|
+
}
|
|
18778
19231
|
function isInteractiveSigner(config) {
|
|
18779
19232
|
if (config.privateKey) {
|
|
18780
19233
|
return false;
|
|
@@ -19140,9 +19593,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19140
19593
|
this._bootstrapSkipped = false;
|
|
19141
19594
|
/**
|
|
19142
19595
|
* Outcome of the last signIn()'s account-bootstrap attempt. `skipped` is
|
|
19143
|
-
* true when bootstrap did not complete (interactive signer,
|
|
19144
|
-
*
|
|
19145
|
-
*
|
|
19596
|
+
* true when bootstrap did not complete in this invocation (interactive signer,
|
|
19597
|
+
* auto-bootstrap disabled, already provisioned, or a decision/provisioning
|
|
19598
|
+
* step failed). `already-provisioned` means the bootstrap was not run here;
|
|
19599
|
+
* it does not mean a prior provisioning attempt failed to complete.
|
|
19600
|
+
* `reason` carries the cause so apps can surface a "finish account setup"
|
|
19601
|
+
* call-to-action. `warnings` is
|
|
19146
19602
|
* present when bootstrap completed, but one or more steps recovered from
|
|
19147
19603
|
* an ambiguous failure (e.g. a KV batch write reconciled via per-space
|
|
19148
19604
|
* fallback) — clean vs. recovered runs are otherwise byte-identical.
|
|
@@ -19325,7 +19781,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19325
19781
|
nonce: config.nonce,
|
|
19326
19782
|
siweConfig: config.siweConfig,
|
|
19327
19783
|
manifest: useBootstrapSignInRequest ? void 0 : config.manifest,
|
|
19328
|
-
capabilityRequest: useBootstrapSignInRequest ? import_sdk_core7.BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
|
|
19784
|
+
capabilityRequest: useBootstrapSignInRequest ? config.includeAccountRegistryPermissions === false ? import_sdk_core7.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core7.BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
|
|
19329
19785
|
includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : config.includeAccountRegistryPermissions
|
|
19330
19786
|
});
|
|
19331
19787
|
this.tc = new import_sdk_core7.TinyCloud(this.auth, {
|
|
@@ -19415,6 +19871,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19415
19871
|
get sessionDid() {
|
|
19416
19872
|
return this.sessionManager.getDID(this.sessionKeyId);
|
|
19417
19873
|
}
|
|
19874
|
+
/** Bare did:key principal used as the credential subject and holder binding. */
|
|
19875
|
+
get credentialHolderDid() {
|
|
19876
|
+
return this.sessionDid.split("#", 1)[0];
|
|
19877
|
+
}
|
|
19878
|
+
/** Canonical verification method for the active credential holder key. */
|
|
19879
|
+
get credentialHolderKid() {
|
|
19880
|
+
const holder = this.credentialHolderDid;
|
|
19881
|
+
return `${holder}#${holder.slice("did:key:".length)}`;
|
|
19882
|
+
}
|
|
19418
19883
|
/**
|
|
19419
19884
|
* Return the current session's signed ReCap capabilities after the session
|
|
19420
19885
|
* has been authenticated or restored. This is intentionally distinct from
|
|
@@ -19568,6 +20033,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19568
20033
|
this._bootstrapSkipped = false;
|
|
19569
20034
|
this._bootstrapStatus = { skipped: false };
|
|
19570
20035
|
if (this.config.autoBootstrapAccount === false) {
|
|
20036
|
+
this._bootstrapStatus = { skipped: true, reason: "auto-bootstrap-disabled" };
|
|
19571
20037
|
return false;
|
|
19572
20038
|
}
|
|
19573
20039
|
if (!this.auth || !this._address) {
|
|
@@ -19582,11 +20048,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19582
20048
|
return false;
|
|
19583
20049
|
}
|
|
19584
20050
|
const steps = (0, import_sdk_core7.bootstrapSteps)(this._address, this._chainId);
|
|
19585
|
-
if (!await this.isFreshBootstrapAccount(steps)) {
|
|
19586
|
-
return false;
|
|
19587
|
-
}
|
|
19588
20051
|
try {
|
|
19589
|
-
const
|
|
20052
|
+
const decision = await this.resolveBootstrapDecision(steps);
|
|
20053
|
+
if (decision.action === "skip") {
|
|
20054
|
+
this._bootstrapStatus = { skipped: true, reason: "already-provisioned" };
|
|
20055
|
+
return false;
|
|
20056
|
+
}
|
|
20057
|
+
const warnings = await this.runAccountBootstrap(steps, { mode: decision.mode });
|
|
20058
|
+
await this.writeBootstrapCompletionMarker(steps);
|
|
19590
20059
|
if (warnings.length > 0) {
|
|
19591
20060
|
this._bootstrapStatus = { skipped: false, warnings };
|
|
19592
20061
|
this.notificationHandler.warning(
|
|
@@ -19605,32 +20074,92 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19605
20074
|
}
|
|
19606
20075
|
return true;
|
|
19607
20076
|
}
|
|
19608
|
-
async
|
|
20077
|
+
async resolveBootstrapDecision(steps) {
|
|
19609
20078
|
const enshrinedSpaceIds = /* @__PURE__ */ new Set();
|
|
19610
20079
|
for (const step of steps) {
|
|
19611
20080
|
if (step.kind === "session") {
|
|
19612
20081
|
enshrinedSpaceIds.add(step.spaceId);
|
|
19613
20082
|
}
|
|
19614
20083
|
}
|
|
19615
|
-
const
|
|
20084
|
+
const auth = this.auth;
|
|
20085
|
+
if (!auth) {
|
|
20086
|
+
throw new Error("Account bootstrap requires an active wallet session");
|
|
20087
|
+
}
|
|
20088
|
+
const skipped = auth.lastActivationSkippedSpaceIds;
|
|
19616
20089
|
if (skipped.some((spaceId) => enshrinedSpaceIds.has(spaceId))) {
|
|
19617
|
-
return
|
|
20090
|
+
return { action: "run", mode: "fresh" };
|
|
19618
20091
|
}
|
|
19619
20092
|
try {
|
|
19620
|
-
const
|
|
19621
|
-
|
|
19622
|
-
|
|
20093
|
+
const accountSpaceId = this.ownedSpaceId(import_sdk_core7.ACCOUNT_REGISTRY_SPACE);
|
|
20094
|
+
const markerPermission = {
|
|
20095
|
+
service: "tinycloud.kv",
|
|
20096
|
+
space: accountSpaceId,
|
|
20097
|
+
path: BOOTSTRAP_COMPLETION_MARKER_KEY,
|
|
20098
|
+
actions: ["get"]
|
|
20099
|
+
};
|
|
20100
|
+
if (!this.hasRuntimePermissions([markerPermission])) {
|
|
20101
|
+
return { action: "run", mode: "repair" };
|
|
19623
20102
|
}
|
|
19624
|
-
|
|
20103
|
+
const marker = await this.readBootstrapCompletionMarker();
|
|
20104
|
+
if (marker.ok) {
|
|
20105
|
+
if (this.isAcceptedBootstrapCompletionMarker(marker.data.data)) {
|
|
20106
|
+
return { action: "skip" };
|
|
20107
|
+
}
|
|
20108
|
+
return { action: "run", mode: "repair" };
|
|
20109
|
+
}
|
|
20110
|
+
if (marker.error.code === import_sdk_core7.ErrorCodes.KV_NOT_FOUND && this.markerReadIsUnhostedSpace(marker.error.meta)) {
|
|
20111
|
+
return { action: "run", mode: "fresh" };
|
|
20112
|
+
}
|
|
20113
|
+
} catch (err) {
|
|
20114
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
20115
|
+
this.notificationHandler.warning(
|
|
20116
|
+
`Account bootstrap decision failed; attempting one bounded repair: ${reason}`
|
|
20117
|
+
);
|
|
20118
|
+
console.warn(`[TinyCloudNode] account bootstrap decision failed: ${reason}`);
|
|
20119
|
+
return { action: "run", mode: "repair" };
|
|
19625
20120
|
}
|
|
19626
|
-
|
|
19627
|
-
|
|
19628
|
-
|
|
19629
|
-
|
|
19630
|
-
|
|
20121
|
+
return { action: "run", mode: "repair" };
|
|
20122
|
+
}
|
|
20123
|
+
async readBootstrapCompletionMarker() {
|
|
20124
|
+
return this.kvForSpace(this.ownedSpaceId(import_sdk_core7.ACCOUNT_REGISTRY_SPACE)).get(
|
|
20125
|
+
BOOTSTRAP_COMPLETION_MARKER_KEY
|
|
20126
|
+
);
|
|
20127
|
+
}
|
|
20128
|
+
async writeBootstrapCompletionMarker(steps) {
|
|
20129
|
+
if (!this._address) {
|
|
20130
|
+
throw new Error("Bootstrap completion marker requires an active wallet session");
|
|
20131
|
+
}
|
|
20132
|
+
const canonicalStepIds = new Set(
|
|
20133
|
+
(0, import_sdk_core7.bootstrapSteps)(this._address, this._chainId).map((step) => step.id)
|
|
20134
|
+
);
|
|
20135
|
+
const providedStepIds = new Set(steps.map((step) => step.id));
|
|
20136
|
+
if (canonicalStepIds.size !== providedStepIds.size || [...canonicalStepIds].some((stepId) => !providedStepIds.has(stepId))) {
|
|
20137
|
+
throw new Error("Bootstrap completion marker requires the canonical bootstrap step set");
|
|
20138
|
+
}
|
|
20139
|
+
const marker = {
|
|
20140
|
+
v: BOOTSTRAP_COMPLETION_MARKER_VERSION,
|
|
20141
|
+
stepIds: [...canonicalStepIds],
|
|
20142
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
20143
|
+
};
|
|
20144
|
+
const written = await this.kvForSpace(this.ownedSpaceId(import_sdk_core7.ACCOUNT_REGISTRY_SPACE)).put(
|
|
20145
|
+
BOOTSTRAP_COMPLETION_MARKER_KEY,
|
|
20146
|
+
marker
|
|
20147
|
+
);
|
|
20148
|
+
if (!written.ok) {
|
|
20149
|
+
throw new Error(`Failed to write bootstrap completion marker: ${written.error.message}`);
|
|
19631
20150
|
}
|
|
19632
20151
|
}
|
|
19633
|
-
|
|
20152
|
+
isAcceptedBootstrapCompletionMarker(value) {
|
|
20153
|
+
if (typeof value !== "object" || value === null) return false;
|
|
20154
|
+
const entries = Object.entries(value);
|
|
20155
|
+
const markerValue = (name) => entries.find(([key2]) => key2 === name)?.[1];
|
|
20156
|
+
const version23 = markerValue("v");
|
|
20157
|
+
return typeof version23 === "number" && Number.isInteger(version23) && ACCEPTED_MARKER_VERSIONS.some((acceptedVersion) => acceptedVersion === version23);
|
|
20158
|
+
}
|
|
20159
|
+
markerReadIsUnhostedSpace(meta) {
|
|
20160
|
+
return meta?.status === 404;
|
|
20161
|
+
}
|
|
20162
|
+
async runAccountBootstrap(steps, { mode } = { mode: "fresh" }) {
|
|
19634
20163
|
if (!this.auth || !this._address) {
|
|
19635
20164
|
throw new Error("Account bootstrap requires an active wallet session");
|
|
19636
20165
|
}
|
|
@@ -19731,9 +20260,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19731
20260
|
if (step.kind === "seed-applications") {
|
|
19732
20261
|
const registered = await this.account.applications.register(
|
|
19733
20262
|
step.manifests.length > 0 ? [...step.manifests] : import_sdk_core7.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
|
|
19734
|
-
//
|
|
19735
|
-
// manifest-hash pre-read
|
|
19736
|
-
// it guards is an INSERT OR REPLACE and is safe to repeat.
|
|
20263
|
+
// The write is an INSERT OR REPLACE and is safe to repeat during a
|
|
20264
|
+
// repair, so skip the manifest-hash pre-read.
|
|
19737
20265
|
{ assumeUnregistered: true }
|
|
19738
20266
|
);
|
|
19739
20267
|
if (!registered.ok) {
|
|
@@ -19741,7 +20269,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
19741
20269
|
}
|
|
19742
20270
|
}
|
|
19743
20271
|
if (step.kind === "encryption-network-create") {
|
|
19744
|
-
await this.ensureEncryptionNetwork(step.networkId, { assumeMissing:
|
|
20272
|
+
await this.ensureEncryptionNetwork(step.networkId, { assumeMissing: mode === "fresh" });
|
|
19745
20273
|
}
|
|
19746
20274
|
if (step.kind === "secret-records-schema") {
|
|
19747
20275
|
const db = this.sqlForSpace(step.spaceId).db(step.database);
|
|
@@ -20180,6 +20708,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20180
20708
|
}
|
|
20181
20709
|
return hosted;
|
|
20182
20710
|
}
|
|
20711
|
+
/** Resolve and authenticate the owner encoded by an owned-space URI. */
|
|
20712
|
+
credentialSpaceOwnerDid(spaceId) {
|
|
20713
|
+
const ownerDid = this.ownerDidFromSpaceId(spaceId);
|
|
20714
|
+
if (ownerDid === void 0 || !didPrincipalMatches2(ownerDid, this.did)) {
|
|
20715
|
+
throw new Error("Credential space owner does not match the active TinyCloud owner");
|
|
20716
|
+
}
|
|
20717
|
+
return ownerDid;
|
|
20718
|
+
}
|
|
20183
20719
|
/**
|
|
20184
20720
|
* Check whether an owned space is already registered/hosted by consulting the
|
|
20185
20721
|
* account spaces registry.
|
|
@@ -20723,6 +21259,66 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20723
21259
|
if (session === void 0) throw new Error("Not signed in. Call signIn() first.");
|
|
20724
21260
|
return signBytesWithJwk(bytes, session.jwk);
|
|
20725
21261
|
}
|
|
21262
|
+
/** Apply only an already-enabled signing policy to the exact credential request. */
|
|
21263
|
+
async autoSignCredentialBytes(bytes) {
|
|
21264
|
+
const strategy = this.config.signStrategy;
|
|
21265
|
+
if (strategy?.type === "auto-sign") return this.signSessionBytes(bytes);
|
|
21266
|
+
if (strategy?.type !== "callback" || !isOpenKeyAutoSignStrategy(strategy)) return void 0;
|
|
21267
|
+
const session = this.currentTinyCloudSession() ?? this._activeServiceSession;
|
|
21268
|
+
if (session === void 0) throw new Error("Not signed in. Call signIn() first.");
|
|
21269
|
+
const request = {
|
|
21270
|
+
address: this.address ?? "",
|
|
21271
|
+
chainId: this.session?.chainId ?? this._chainId,
|
|
21272
|
+
message: new TextDecoder().decode(bytes),
|
|
21273
|
+
type: "message",
|
|
21274
|
+
purpose: "message"
|
|
21275
|
+
};
|
|
21276
|
+
const decision = await strategy.handler(request);
|
|
21277
|
+
if (!decision.approved) {
|
|
21278
|
+
if (decision.needsApproval) return void 0;
|
|
21279
|
+
throw new Error(decision.reason ?? "OpenKey automatic credential signing was rejected");
|
|
21280
|
+
}
|
|
21281
|
+
if (typeof decision.signature !== "string" || !await (0, import_sdk_core7.verifyEip191MessageSignature)(
|
|
21282
|
+
request.message,
|
|
21283
|
+
decision.signature,
|
|
21284
|
+
request.address
|
|
21285
|
+
)) {
|
|
21286
|
+
throw new Error("OpenKey credential signature evidence is invalid");
|
|
21287
|
+
}
|
|
21288
|
+
return this.signSessionBytes(bytes);
|
|
21289
|
+
}
|
|
21290
|
+
/** Invoke the configured interactive approval strategy before session signing. */
|
|
21291
|
+
async approveCredentialBytes(bytes) {
|
|
21292
|
+
const strategy = this.config.signStrategy;
|
|
21293
|
+
const session = this.currentTinyCloudSession() ?? this._activeServiceSession;
|
|
21294
|
+
if (session === void 0) throw new Error("Not signed in. Call signIn() first.");
|
|
21295
|
+
const request = {
|
|
21296
|
+
address: this.address ?? "",
|
|
21297
|
+
chainId: this.session?.chainId ?? this._chainId,
|
|
21298
|
+
message: new TextDecoder().decode(bytes),
|
|
21299
|
+
type: "message",
|
|
21300
|
+
purpose: "message"
|
|
21301
|
+
};
|
|
21302
|
+
const approval = isOpenKeyAutoSignStrategy(strategy) ? openKeyApproval(strategy) : strategy?.type === "callback" ? strategy.handler : void 0;
|
|
21303
|
+
if (approval) {
|
|
21304
|
+
const decision = await approval(request);
|
|
21305
|
+
if (!decision.approved) throw new Error(decision.reason ?? "Credential signing was rejected");
|
|
21306
|
+
if (decision.signature !== void 0 && !await (0, import_sdk_core7.verifyEip191MessageSignature)(
|
|
21307
|
+
request.message,
|
|
21308
|
+
decision.signature,
|
|
21309
|
+
request.address
|
|
21310
|
+
)) {
|
|
21311
|
+
throw new Error("OpenKey credential signature evidence is invalid");
|
|
21312
|
+
}
|
|
21313
|
+
return this.signSessionBytes(bytes);
|
|
21314
|
+
}
|
|
21315
|
+
if (strategy?.type === "auto-reject") throw new Error("Credential signing was rejected");
|
|
21316
|
+
if (this.config.signer) {
|
|
21317
|
+
await this.config.signer.signMessage(request.message);
|
|
21318
|
+
return this.signSessionBytes(bytes);
|
|
21319
|
+
}
|
|
21320
|
+
throw new Error("Interactive OpenKey approval is not configured");
|
|
21321
|
+
}
|
|
20726
21322
|
/** Bind a session-signed invocation to the canonical service audience. */
|
|
20727
21323
|
async bindInvocationAudience(authorization, audience) {
|
|
20728
21324
|
const session = this.currentTinyCloudSession() ?? this._activeServiceSession;
|
|
@@ -20790,7 +21386,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20790
21386
|
nonce: this.config.nonce,
|
|
20791
21387
|
siweConfig: this.config.siweConfig,
|
|
20792
21388
|
manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
|
|
20793
|
-
capabilityRequest: useBootstrapSignInRequest ? import_sdk_core7.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
|
|
21389
|
+
capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core7.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core7.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
|
|
20794
21390
|
includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
|
|
20795
21391
|
});
|
|
20796
21392
|
this.tc = new import_sdk_core7.TinyCloud(this.auth, {
|
|
@@ -20843,7 +21439,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20843
21439
|
nonce: this.config.nonce,
|
|
20844
21440
|
siweConfig: this.config.siweConfig,
|
|
20845
21441
|
manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
|
|
20846
|
-
capabilityRequest: useBootstrapSignInRequest ? import_sdk_core7.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
|
|
21442
|
+
capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core7.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core7.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
|
|
20847
21443
|
includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
|
|
20848
21444
|
});
|
|
20849
21445
|
this.tc = new import_sdk_core7.TinyCloud(this.auth, {
|
|
@@ -23592,35 +24188,44 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
23592
24188
|
if (parentDelegation.disableSubDelegation) {
|
|
23593
24189
|
throw new Error("Parent delegation does not allow sub-delegation");
|
|
23594
24190
|
}
|
|
23595
|
-
|
|
24191
|
+
const parentResources = parentDelegation.resources ?? [{
|
|
24192
|
+
service: parentDelegation.actions[0]?.split("/", 1)[0]?.replace(/^tinycloud\./, "") ?? "kv",
|
|
24193
|
+
space: parentDelegation.spaceId,
|
|
24194
|
+
path: parentDelegation.path,
|
|
24195
|
+
actions: parentDelegation.actions
|
|
24196
|
+
}];
|
|
24197
|
+
const requestedResources = params.resources ?? [{
|
|
24198
|
+
service: params.actions[0]?.split("/", 1)[0]?.replace(/^tinycloud\./, "") ?? "kv",
|
|
24199
|
+
space: parentDelegation.spaceId,
|
|
24200
|
+
path: params.path,
|
|
24201
|
+
actions: params.actions
|
|
24202
|
+
}];
|
|
24203
|
+
const resourceIsContained = (parent, child) => {
|
|
24204
|
+
const parentEncryption = parent.service === "encryption" || parent.service === "tinycloud.encryption";
|
|
24205
|
+
const childEncryption = child.service === "encryption" || child.service === "tinycloud.encryption";
|
|
24206
|
+
if (parentEncryption || childEncryption) return parentEncryption && childEncryption && parent.path === child.path && child.actions.every((action) => parent.actions.includes(action));
|
|
24207
|
+
const pathContained = parent.path === child.path || parent.path.endsWith("/") && child.path.startsWith(parent.path) || child.path.startsWith(`${parent.path}/`);
|
|
24208
|
+
return pathContained && child.actions.every((action) => parent.actions.includes(action));
|
|
24209
|
+
};
|
|
24210
|
+
if (requestedResources.length === 0 || requestedResources.some((child) => !parentResources.some((parent) => resourceIsContained(parent, child)))) {
|
|
23596
24211
|
throw new Error(
|
|
23597
|
-
|
|
24212
|
+
"Sub-delegation resources exceed the received delegation"
|
|
23598
24213
|
);
|
|
23599
24214
|
}
|
|
23600
|
-
const parentActions = new Set(parentDelegation.actions);
|
|
23601
|
-
for (const action of params.actions) {
|
|
23602
|
-
if (!parentActions.has(action)) {
|
|
23603
|
-
throw new Error(
|
|
23604
|
-
`Sub-delegation action "${action}" is not in parent's actions: ${parentDelegation.actions.join(", ")}`
|
|
23605
|
-
);
|
|
23606
|
-
}
|
|
23607
|
-
}
|
|
23608
24215
|
const now = /* @__PURE__ */ new Date();
|
|
23609
24216
|
const expiryMs = params.expiryMs ?? 60 * 60 * 1e3;
|
|
23610
24217
|
const requestedExpiry = new Date(now.getTime() + expiryMs);
|
|
23611
24218
|
const actualExpiry = requestedExpiry > parentDelegation.expiry ? parentDelegation.expiry : requestedExpiry;
|
|
23612
24219
|
const abilities = {};
|
|
23613
|
-
const
|
|
23614
|
-
const
|
|
23615
|
-
|
|
23616
|
-
|
|
23617
|
-
|
|
23618
|
-
|
|
23619
|
-
|
|
23620
|
-
abilities
|
|
23621
|
-
|
|
23622
|
-
if (duckdbActions.length > 0) {
|
|
23623
|
-
abilities.duckdb = { [params.path]: duckdbActions };
|
|
24220
|
+
const rawAbilities = {};
|
|
24221
|
+
for (const resource of requestedResources) {
|
|
24222
|
+
const service = resource.service.replace(/^tinycloud\./, "");
|
|
24223
|
+
if (service === "encryption") {
|
|
24224
|
+
rawAbilities[resource.path] = [...resource.actions];
|
|
24225
|
+
continue;
|
|
24226
|
+
}
|
|
24227
|
+
abilities[service] ?? (abilities[service] = {});
|
|
24228
|
+
abilities[service][resource.path] = [...resource.actions];
|
|
23624
24229
|
}
|
|
23625
24230
|
const targetHost = parentDelegation.host ?? this.config.host;
|
|
23626
24231
|
const prepared = this.wasmBindings.prepareSession({
|
|
@@ -23632,7 +24237,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
23632
24237
|
expirationTime: actualExpiry.toISOString(),
|
|
23633
24238
|
spaceId: parentDelegation.spaceId,
|
|
23634
24239
|
delegateUri: params.delegateDID,
|
|
23635
|
-
parents: [parentDelegation.cid]
|
|
24240
|
+
parents: [parentDelegation.cid],
|
|
24241
|
+
...Object.keys(rawAbilities).length > 0 ? { rawAbilities } : {}
|
|
23636
24242
|
});
|
|
23637
24243
|
const signature2 = await this.signer.signMessage(prepared.siwe);
|
|
23638
24244
|
const subDelegationSession = this.wasmBindings.completeSessionSetup({
|
|
@@ -23650,14 +24256,20 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
23650
24256
|
cid: subDelegationSession.delegationCid,
|
|
23651
24257
|
delegationHeader: subDelegationSession.delegationHeader,
|
|
23652
24258
|
spaceId: parentDelegation.spaceId,
|
|
23653
|
-
path:
|
|
23654
|
-
actions:
|
|
24259
|
+
path: requestedResources[0].path,
|
|
24260
|
+
actions: requestedResources[0].actions,
|
|
23655
24261
|
disableSubDelegation: params.disableSubDelegation ?? false,
|
|
23656
24262
|
expiry: actualExpiry,
|
|
23657
24263
|
delegateDID: params.delegateDID,
|
|
23658
24264
|
ownerAddress: parentDelegation.ownerAddress,
|
|
23659
24265
|
chainId: parentDelegation.chainId,
|
|
23660
|
-
host: targetHost
|
|
24266
|
+
host: targetHost,
|
|
24267
|
+
resources: requestedResources.map((resource) => ({
|
|
24268
|
+
service: resource.service.replace(/^tinycloud\./, ""),
|
|
24269
|
+
space: resource.service.replace(/^tinycloud\./, "") === "encryption" ? "encryption" : resource.space ?? parentDelegation.spaceId,
|
|
24270
|
+
path: resource.path,
|
|
24271
|
+
actions: [...resource.actions]
|
|
24272
|
+
}))
|
|
23661
24273
|
};
|
|
23662
24274
|
}
|
|
23663
24275
|
};
|
|
@@ -23804,6 +24416,50 @@ var FileSessionStorage = class {
|
|
|
23804
24416
|
}
|
|
23805
24417
|
};
|
|
23806
24418
|
|
|
24419
|
+
// src/authorization/openKeyBridge.ts
|
|
24420
|
+
function wireOpenKeyAuthorize(openkey) {
|
|
24421
|
+
return async (input) => {
|
|
24422
|
+
const result = await openkey.authorizeTinyCloud({
|
|
24423
|
+
protocolVersion: 1,
|
|
24424
|
+
siwe: input.siwe,
|
|
24425
|
+
keyId: input.keyId,
|
|
24426
|
+
jwk: input.jwk,
|
|
24427
|
+
host: input.host,
|
|
24428
|
+
// Forward the presentation envelope verbatim — the OpenKey SDK
|
|
24429
|
+
// validates and size-bounds it before use.
|
|
24430
|
+
presentation: input.presentation
|
|
24431
|
+
});
|
|
24432
|
+
if (result.protocolVersion !== 1) {
|
|
24433
|
+
throw new Error(
|
|
24434
|
+
`wireOpenKeyAuthorize: OpenKey returned unsupported protocolVersion ${result.protocolVersion}`
|
|
24435
|
+
);
|
|
24436
|
+
}
|
|
24437
|
+
if (typeof result.signedMessage !== "string" || !result.signedMessage) {
|
|
24438
|
+
throw new Error(
|
|
24439
|
+
"wireOpenKeyAuthorize: OpenKey returned no signedMessage \u2014 cannot complete a TinyCloud session"
|
|
24440
|
+
);
|
|
24441
|
+
}
|
|
24442
|
+
if (!Array.isArray(result.selectedActionKeys)) {
|
|
24443
|
+
throw new Error(
|
|
24444
|
+
"wireOpenKeyAuthorize: OpenKey returned no selectedActionKeys"
|
|
24445
|
+
);
|
|
24446
|
+
}
|
|
24447
|
+
if (!Array.isArray(result.permissions)) {
|
|
24448
|
+
throw new Error(
|
|
24449
|
+
"wireOpenKeyAuthorize: OpenKey returned no permissions"
|
|
24450
|
+
);
|
|
24451
|
+
}
|
|
24452
|
+
return {
|
|
24453
|
+
protocolVersion: 1,
|
|
24454
|
+
address: result.address,
|
|
24455
|
+
signature: result.signature,
|
|
24456
|
+
signedMessage: result.signedMessage,
|
|
24457
|
+
selectedActionKeys: result.selectedActionKeys,
|
|
24458
|
+
permissions: result.permissions
|
|
24459
|
+
};
|
|
24460
|
+
};
|
|
24461
|
+
}
|
|
24462
|
+
|
|
23807
24463
|
// src/index.ts
|
|
23808
24464
|
var import_sdk_core12 = require("@tinycloud/sdk-core");
|
|
23809
24465
|
|
|
@@ -23892,6 +24548,14 @@ function signedAuthorityFromCompactUcan(authorization) {
|
|
|
23892
24548
|
if (typeof payload.aud !== "string" || payload.aud.length === 0) {
|
|
23893
24549
|
throw new Error("Validated runtime delegation is missing a signed audience.");
|
|
23894
24550
|
}
|
|
24551
|
+
if (typeof payload.iss !== "string" || payload.iss.length === 0) {
|
|
24552
|
+
throw new Error("Validated runtime delegation is missing a signed issuer.");
|
|
24553
|
+
}
|
|
24554
|
+
if (!Array.isArray(payload.prf) || payload.prf.some(
|
|
24555
|
+
(proof) => typeof proof !== "string" || proof.length === 0
|
|
24556
|
+
)) {
|
|
24557
|
+
throw new Error("Validated runtime delegation has malformed signed proofs.");
|
|
24558
|
+
}
|
|
23895
24559
|
if (typeof payload.exp !== "number" || !Number.isFinite(payload.exp)) {
|
|
23896
24560
|
throw new Error("Validated runtime delegation is missing a signed expiry.");
|
|
23897
24561
|
}
|
|
@@ -23902,6 +24566,11 @@ function signedAuthorityFromCompactUcan(authorization) {
|
|
|
23902
24566
|
if (payload.att === null || typeof payload.att !== "object" || Array.isArray(payload.att)) {
|
|
23903
24567
|
throw new Error("Validated runtime delegation is missing a signed attenuation.");
|
|
23904
24568
|
}
|
|
24569
|
+
const fact = Array.isArray(payload.fct) && payload.fct.length > 0 && payload.fct[0] !== null && typeof payload.fct[0] === "object" && !Array.isArray(payload.fct[0]) ? payload.fct[0] : void 0;
|
|
24570
|
+
const remainingRedelegationDepth = fact?.remainingRedelegationDepth;
|
|
24571
|
+
if (remainingRedelegationDepth !== void 0 && (!Number.isInteger(remainingRedelegationDepth) || remainingRedelegationDepth < 0 || remainingRedelegationDepth > 8)) {
|
|
24572
|
+
throw new Error("Validated runtime delegation has invalid signed redelegation depth.");
|
|
24573
|
+
}
|
|
23905
24574
|
const permissions = [];
|
|
23906
24575
|
for (const [resource, abilities] of Object.entries(payload.att)) {
|
|
23907
24576
|
if (abilities === null || typeof abilities !== "object" || Array.isArray(abilities)) {
|
|
@@ -23952,8 +24621,11 @@ function signedAuthorityFromCompactUcan(authorization) {
|
|
|
23952
24621
|
...permission.caveats === void 0 ? {} : { caveats: permission.caveats }
|
|
23953
24622
|
}));
|
|
23954
24623
|
return {
|
|
24624
|
+
issuer: payload.iss,
|
|
23955
24625
|
audience: payload.aud,
|
|
23956
24626
|
expiry,
|
|
24627
|
+
proofs: [...payload.prf],
|
|
24628
|
+
...remainingRedelegationDepth === void 0 ? {} : { remainingRedelegationDepth },
|
|
23957
24629
|
permissions: canonicalPermissions,
|
|
23958
24630
|
resources: canonicalResources
|
|
23959
24631
|
};
|
|
@@ -24044,6 +24716,13 @@ async function activateValidatedRuntimeDelegation(node, delegation, options) {
|
|
|
24044
24716
|
delegationHeader: { Authorization: authorization },
|
|
24045
24717
|
ownerAddress: delegation.ownerAddress,
|
|
24046
24718
|
chainId: delegation.chainId,
|
|
24719
|
+
delegatorDID: signed2.issuer,
|
|
24720
|
+
...signed2.proofs.length === 1 ? { parentCid: signed2.proofs[0] } : {},
|
|
24721
|
+
...signed2.remainingRedelegationDepth === void 0 ? {} : {
|
|
24722
|
+
allowSubDelegation: signed2.remainingRedelegationDepth > 0,
|
|
24723
|
+
disableSubDelegation: signed2.remainingRedelegationDepth === 0
|
|
24724
|
+
},
|
|
24725
|
+
authHeader: authorization,
|
|
24047
24726
|
spaceId: signedSpace ?? delegation.spaceId,
|
|
24048
24727
|
path: primary.path,
|
|
24049
24728
|
actions: [...primary.actions],
|
|
@@ -24137,10 +24816,13 @@ var import_sdk_core22 = require("@tinycloud/sdk-core");
|
|
|
24137
24816
|
var import_sdk_core23 = require("@tinycloud/sdk-core");
|
|
24138
24817
|
// Annotate the CommonJS export names for ESM import in node:
|
|
24139
24818
|
0 && (module.exports = {
|
|
24819
|
+
ACCEPTED_MARKER_VERSIONS,
|
|
24140
24820
|
ACCOUNT_REGISTRY_PATH,
|
|
24141
24821
|
ACCOUNT_REGISTRY_SPACE,
|
|
24142
24822
|
AccountService,
|
|
24143
24823
|
AutoApproveSpaceCreationHandler,
|
|
24824
|
+
BOOTSTRAP_COMPLETION_MARKER_KEY,
|
|
24825
|
+
BOOTSTRAP_COMPLETION_MARKER_VERSION,
|
|
24144
24826
|
CapabilityKeyRegistry,
|
|
24145
24827
|
CapabilityKeyRegistryErrorCodes,
|
|
24146
24828
|
CaveatedDelegationUnsupportedError,
|
|
@@ -24277,7 +24959,8 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
|
|
|
24277
24959
|
tinyCloudDebugLogger,
|
|
24278
24960
|
validateEnvelope,
|
|
24279
24961
|
validateManifest,
|
|
24280
|
-
verifyDecryptResponse
|
|
24962
|
+
verifyDecryptResponse,
|
|
24963
|
+
wireOpenKeyAuthorize
|
|
24281
24964
|
});
|
|
24282
24965
|
/*! Bundled license information:
|
|
24283
24966
|
|