@tinycloud/node-sdk 2.11.0-beta.1 → 2.11.0-beta.4
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-CQ_5wXQT.d.cts → core-BmfrcQcJ.d.cts} +70 -6
- package/dist/{core-CQ_5wXQT.d.ts → core-BmfrcQcJ.d.ts} +70 -6
- package/dist/core.cjs +79 -8
- 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 +79 -8
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +79 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +79 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -195,9 +195,9 @@ interface NodeUserAuthorizationConfig {
|
|
|
195
195
|
tinycloudRegistryUrl?: string | null;
|
|
196
196
|
/** Fallback TinyCloud hosts. Default: hosted TinyCloud node. */
|
|
197
197
|
tinycloudFallbackHosts?: string[] | null;
|
|
198
|
-
/** Probe
|
|
198
|
+
/** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
|
|
199
199
|
autoDiscoverLocalNode?: boolean;
|
|
200
|
-
/** Local loopback node URL to probe.
|
|
200
|
+
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
201
201
|
localNodeUrl?: string;
|
|
202
202
|
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
203
203
|
localLinkName?: string;
|
|
@@ -319,6 +319,12 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
319
319
|
private _address?;
|
|
320
320
|
private _chainId?;
|
|
321
321
|
private _nodeFeatures;
|
|
322
|
+
/**
|
|
323
|
+
* `nodeId` from the `GET /info` performed during sign-in/restore, tagged with
|
|
324
|
+
* the host it came from. Callers that need the node DID (encryption-network
|
|
325
|
+
* admin invocations) reuse this instead of re-fetching `/info`.
|
|
326
|
+
*/
|
|
327
|
+
private _nodeInfoIdentity?;
|
|
322
328
|
private _lastActivationSkippedSpaceIds;
|
|
323
329
|
constructor(config: NodeUserAuthorizationConfig);
|
|
324
330
|
/**
|
|
@@ -387,6 +393,13 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
387
393
|
private requireTinyCloudHosts;
|
|
388
394
|
private get primaryTinyCloudHost();
|
|
389
395
|
get nodeFeatures(): string[];
|
|
396
|
+
/**
|
|
397
|
+
* The node DID reported by `GET /info` for `host`, if the sign-in (or
|
|
398
|
+
* restore) that populated it targeted that same host. Returns `undefined`
|
|
399
|
+
* for any other host, and for nodes whose `/info` omits `nodeId`, so callers
|
|
400
|
+
* fall back to fetching it themselves rather than using a foreign node's DID.
|
|
401
|
+
*/
|
|
402
|
+
nodeIdForHost(host: string): string | undefined;
|
|
390
403
|
get lastActivationSkippedSpaceIds(): string[];
|
|
391
404
|
/**
|
|
392
405
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
@@ -887,9 +900,9 @@ interface TinyCloudNodeConfig {
|
|
|
887
900
|
tinycloudRegistryUrl?: string | null;
|
|
888
901
|
/** Fallback TinyCloud hosts. Default: hosted TinyCloud node. */
|
|
889
902
|
tinycloudFallbackHosts?: string[] | null;
|
|
890
|
-
/** Probe
|
|
903
|
+
/** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
|
|
891
904
|
autoDiscoverLocalNode?: boolean;
|
|
892
|
-
/** Local loopback node URL to probe.
|
|
905
|
+
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
893
906
|
localNodeUrl?: string;
|
|
894
907
|
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
895
908
|
localLinkName?: string;
|
|
@@ -987,6 +1000,21 @@ interface RuntimePermissionGrantOptions {
|
|
|
987
1000
|
/** Override expiry. ms-format string ("7d", "1h") or raw milliseconds. */
|
|
988
1001
|
expiry?: string | number;
|
|
989
1002
|
}
|
|
1003
|
+
interface EnsureEncryptionNetworkOptions {
|
|
1004
|
+
/**
|
|
1005
|
+
* Skip the `GET /encryption/networks/{id}` existence probe and go straight
|
|
1006
|
+
* to the create.
|
|
1007
|
+
*
|
|
1008
|
+
* The probe pays for itself only when the network already exists. On a
|
|
1009
|
+
* freshly bootstrapped account it is a guaranteed 404, so it costs a round
|
|
1010
|
+
* trip on the cold sign-in path and saves nothing. Creating without it is
|
|
1011
|
+
* safe: the server answers `409 Conflict` if the network is already there,
|
|
1012
|
+
* which {@link TinyCloudNode.createEncryptionNetwork} resolves by reading the
|
|
1013
|
+
* existing descriptor. Set this only when the caller knows the account was
|
|
1014
|
+
* just provisioned.
|
|
1015
|
+
*/
|
|
1016
|
+
assumeMissing?: boolean;
|
|
1017
|
+
}
|
|
990
1018
|
/**
|
|
991
1019
|
* High-level TinyCloud API for Node.js environments.
|
|
992
1020
|
*
|
|
@@ -1044,6 +1072,12 @@ declare class TinyCloudNode {
|
|
|
1044
1072
|
* so this avoids re-parsing the recap on every registration.
|
|
1045
1073
|
*/
|
|
1046
1074
|
private _recapOperationsCache?;
|
|
1075
|
+
/**
|
|
1076
|
+
* Owned space ids this sign-in has already confirmed are hosted. Consulted by
|
|
1077
|
+
* {@link ensureOwnedSpaceHostedById}; cleared on every {@link signIn} because
|
|
1078
|
+
* hosting is confirmed against the session that was active at the time.
|
|
1079
|
+
*/
|
|
1080
|
+
private readonly confirmedHostedSpaceIds;
|
|
1047
1081
|
/**
|
|
1048
1082
|
* TinyCloudSession captured by {@link restoreSession} when there's no
|
|
1049
1083
|
* auth-layer signer available (session-only mode used by OpenKey-backed
|
|
@@ -1252,6 +1286,22 @@ declare class TinyCloudNode {
|
|
|
1252
1286
|
private withAccountRegistryRetry;
|
|
1253
1287
|
private requestedEncryptionNetworkIds;
|
|
1254
1288
|
private ensureRequestedEncryptionNetworks;
|
|
1289
|
+
/**
|
|
1290
|
+
* Ensure one of this user's owned spaces is hosted, at most once per space
|
|
1291
|
+
* per sign-in.
|
|
1292
|
+
*
|
|
1293
|
+
* Account bootstrap funnels six calls through here (via
|
|
1294
|
+
* `AccountService.ensureAccountSpaceHosted`), and each one re-submits
|
|
1295
|
+
* `activateSessionWithHost` with the *primary* session. That session's recap
|
|
1296
|
+
* covers only `default` and `secrets`, so the account space appears in
|
|
1297
|
+
* neither `activated` nor `skipped` and the guard below returns immediately
|
|
1298
|
+
* — the repeat calls cannot change the outcome, they only cost round trips.
|
|
1299
|
+
*
|
|
1300
|
+
* The memo is per sign-in ({@link confirmedHostedSpaceIds} is cleared in
|
|
1301
|
+
* `signIn`) and only records confirmed successes. A wrong skip is
|
|
1302
|
+
* self-revealing: the next write to the space fails immediately and loudly
|
|
1303
|
+
* with `404 Space not found`.
|
|
1304
|
+
*/
|
|
1255
1305
|
private ensureOwnedSpaceHostedById;
|
|
1256
1306
|
/**
|
|
1257
1307
|
* Host one of this user's owned spaces by name (e.g. `"applications"`).
|
|
@@ -1462,6 +1512,14 @@ declare class TinyCloudNode {
|
|
|
1462
1512
|
*/
|
|
1463
1513
|
private requireEncryptionSession;
|
|
1464
1514
|
private createEncryptionCrypto;
|
|
1515
|
+
/**
|
|
1516
|
+
* The node DID for {@link config.host}.
|
|
1517
|
+
*
|
|
1518
|
+
* Sign-in already performs `GET /info` for the protocol-version check, and
|
|
1519
|
+
* that response carries `nodeId`, so reuse it rather than fetching `/info` a
|
|
1520
|
+
* second time. Only a value recorded for this exact host qualifies; older
|
|
1521
|
+
* nodes that omit `nodeId` fall through to the fetch.
|
|
1522
|
+
*/
|
|
1465
1523
|
private fetchNodeId;
|
|
1466
1524
|
private signRawNetworkAuthorization;
|
|
1467
1525
|
private fetchEncryptionNetworkAt;
|
|
@@ -1586,7 +1644,13 @@ declare class TinyCloudNode {
|
|
|
1586
1644
|
get encryption(): IEncryptionService;
|
|
1587
1645
|
getEncryptionNetwork(nameOrNetworkId?: string): Promise<NetworkDescriptor | null>;
|
|
1588
1646
|
createEncryptionNetwork(name?: string): Promise<NetworkDescriptor>;
|
|
1589
|
-
|
|
1647
|
+
/**
|
|
1648
|
+
* Ensure an encryption network exists, creating it if necessary.
|
|
1649
|
+
*
|
|
1650
|
+
* @param nameOrNetworkId - Network name or full `urn:tinycloud:encryption:` id.
|
|
1651
|
+
* @param options - See {@link EnsureEncryptionNetworkOptions}.
|
|
1652
|
+
*/
|
|
1653
|
+
ensureEncryptionNetwork(nameOrNetworkId?: string, options?: EnsureEncryptionNetworkOptions): Promise<NetworkDescriptor>;
|
|
1590
1654
|
/**
|
|
1591
1655
|
* App-facing secrets API backed by the `secrets` space vault.
|
|
1592
1656
|
*/
|
|
@@ -2168,4 +2232,4 @@ declare class WasmKeyProvider implements KeyProvider {
|
|
|
2168
2232
|
*/
|
|
2169
2233
|
declare function createWasmKeyProvider(sessionManager: SessionManagerWithListing): WasmKeyProvider;
|
|
2170
2234
|
|
|
2171
|
-
export { type AuthDelegationArtifact as A, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, FileSessionStorage as F, MemorySessionStorage as M, type NodeEventEmitterStrategy as N, type OwnerDelegationReceipt as O, type PortableDelegation as P, type RestorableSession as R, type SecretPermissionHint as S, TinyCloudNode as T, UnsupportedSessionRestoreError as U, type ValidatedRuntimeDelegation as V, WasmKeyProvider as W, type AuthRequestArtifact as a, type DelegateToResult as b, DelegatedAccess as c, type DelegationAuthority as d, NodeUserAuthorization as e, type NodeUserAuthorizationConfig as f, type RuntimeDelegationActivator as g, type RuntimePermissionGrantOptions as h, type SecretReadInput as i, type SecretReadResult as j, type SignStrategy as k, type TinyCloudNodeConfig as l, type WasmKeyProviderConfig as m, activateValidatedRuntimeDelegation as n, createWasmKeyProvider as o, defaultSignStrategy as p, deserializeDelegation as q, grantAuthRequest as r, serializeDelegation as s };
|
|
2235
|
+
export { type AuthDelegationArtifact as A, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, type EnsureEncryptionNetworkOptions as E, FileSessionStorage as F, MemorySessionStorage as M, type NodeEventEmitterStrategy as N, type OwnerDelegationReceipt as O, type PortableDelegation as P, type RestorableSession as R, type SecretPermissionHint as S, TinyCloudNode as T, UnsupportedSessionRestoreError as U, type ValidatedRuntimeDelegation as V, WasmKeyProvider as W, type AuthRequestArtifact as a, type DelegateToResult as b, DelegatedAccess as c, type DelegationAuthority as d, NodeUserAuthorization as e, type NodeUserAuthorizationConfig as f, type RuntimeDelegationActivator as g, type RuntimePermissionGrantOptions as h, type SecretReadInput as i, type SecretReadResult as j, type SignStrategy as k, type TinyCloudNodeConfig as l, type WasmKeyProviderConfig as m, activateValidatedRuntimeDelegation as n, createWasmKeyProvider as o, defaultSignStrategy as p, deserializeDelegation as q, grantAuthRequest as r, serializeDelegation as s };
|
|
@@ -195,9 +195,9 @@ interface NodeUserAuthorizationConfig {
|
|
|
195
195
|
tinycloudRegistryUrl?: string | null;
|
|
196
196
|
/** Fallback TinyCloud hosts. Default: hosted TinyCloud node. */
|
|
197
197
|
tinycloudFallbackHosts?: string[] | null;
|
|
198
|
-
/** Probe
|
|
198
|
+
/** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
|
|
199
199
|
autoDiscoverLocalNode?: boolean;
|
|
200
|
-
/** Local loopback node URL to probe.
|
|
200
|
+
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
201
201
|
localNodeUrl?: string;
|
|
202
202
|
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
203
203
|
localLinkName?: string;
|
|
@@ -319,6 +319,12 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
319
319
|
private _address?;
|
|
320
320
|
private _chainId?;
|
|
321
321
|
private _nodeFeatures;
|
|
322
|
+
/**
|
|
323
|
+
* `nodeId` from the `GET /info` performed during sign-in/restore, tagged with
|
|
324
|
+
* the host it came from. Callers that need the node DID (encryption-network
|
|
325
|
+
* admin invocations) reuse this instead of re-fetching `/info`.
|
|
326
|
+
*/
|
|
327
|
+
private _nodeInfoIdentity?;
|
|
322
328
|
private _lastActivationSkippedSpaceIds;
|
|
323
329
|
constructor(config: NodeUserAuthorizationConfig);
|
|
324
330
|
/**
|
|
@@ -387,6 +393,13 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
387
393
|
private requireTinyCloudHosts;
|
|
388
394
|
private get primaryTinyCloudHost();
|
|
389
395
|
get nodeFeatures(): string[];
|
|
396
|
+
/**
|
|
397
|
+
* The node DID reported by `GET /info` for `host`, if the sign-in (or
|
|
398
|
+
* restore) that populated it targeted that same host. Returns `undefined`
|
|
399
|
+
* for any other host, and for nodes whose `/info` omits `nodeId`, so callers
|
|
400
|
+
* fall back to fetching it themselves rather than using a foreign node's DID.
|
|
401
|
+
*/
|
|
402
|
+
nodeIdForHost(host: string): string | undefined;
|
|
390
403
|
get lastActivationSkippedSpaceIds(): string[];
|
|
391
404
|
/**
|
|
392
405
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
@@ -887,9 +900,9 @@ interface TinyCloudNodeConfig {
|
|
|
887
900
|
tinycloudRegistryUrl?: string | null;
|
|
888
901
|
/** Fallback TinyCloud hosts. Default: hosted TinyCloud node. */
|
|
889
902
|
tinycloudFallbackHosts?: string[] | null;
|
|
890
|
-
/** Probe
|
|
903
|
+
/** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
|
|
891
904
|
autoDiscoverLocalNode?: boolean;
|
|
892
|
-
/** Local loopback node URL to probe.
|
|
905
|
+
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
893
906
|
localNodeUrl?: string;
|
|
894
907
|
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
895
908
|
localLinkName?: string;
|
|
@@ -987,6 +1000,21 @@ interface RuntimePermissionGrantOptions {
|
|
|
987
1000
|
/** Override expiry. ms-format string ("7d", "1h") or raw milliseconds. */
|
|
988
1001
|
expiry?: string | number;
|
|
989
1002
|
}
|
|
1003
|
+
interface EnsureEncryptionNetworkOptions {
|
|
1004
|
+
/**
|
|
1005
|
+
* Skip the `GET /encryption/networks/{id}` existence probe and go straight
|
|
1006
|
+
* to the create.
|
|
1007
|
+
*
|
|
1008
|
+
* The probe pays for itself only when the network already exists. On a
|
|
1009
|
+
* freshly bootstrapped account it is a guaranteed 404, so it costs a round
|
|
1010
|
+
* trip on the cold sign-in path and saves nothing. Creating without it is
|
|
1011
|
+
* safe: the server answers `409 Conflict` if the network is already there,
|
|
1012
|
+
* which {@link TinyCloudNode.createEncryptionNetwork} resolves by reading the
|
|
1013
|
+
* existing descriptor. Set this only when the caller knows the account was
|
|
1014
|
+
* just provisioned.
|
|
1015
|
+
*/
|
|
1016
|
+
assumeMissing?: boolean;
|
|
1017
|
+
}
|
|
990
1018
|
/**
|
|
991
1019
|
* High-level TinyCloud API for Node.js environments.
|
|
992
1020
|
*
|
|
@@ -1044,6 +1072,12 @@ declare class TinyCloudNode {
|
|
|
1044
1072
|
* so this avoids re-parsing the recap on every registration.
|
|
1045
1073
|
*/
|
|
1046
1074
|
private _recapOperationsCache?;
|
|
1075
|
+
/**
|
|
1076
|
+
* Owned space ids this sign-in has already confirmed are hosted. Consulted by
|
|
1077
|
+
* {@link ensureOwnedSpaceHostedById}; cleared on every {@link signIn} because
|
|
1078
|
+
* hosting is confirmed against the session that was active at the time.
|
|
1079
|
+
*/
|
|
1080
|
+
private readonly confirmedHostedSpaceIds;
|
|
1047
1081
|
/**
|
|
1048
1082
|
* TinyCloudSession captured by {@link restoreSession} when there's no
|
|
1049
1083
|
* auth-layer signer available (session-only mode used by OpenKey-backed
|
|
@@ -1252,6 +1286,22 @@ declare class TinyCloudNode {
|
|
|
1252
1286
|
private withAccountRegistryRetry;
|
|
1253
1287
|
private requestedEncryptionNetworkIds;
|
|
1254
1288
|
private ensureRequestedEncryptionNetworks;
|
|
1289
|
+
/**
|
|
1290
|
+
* Ensure one of this user's owned spaces is hosted, at most once per space
|
|
1291
|
+
* per sign-in.
|
|
1292
|
+
*
|
|
1293
|
+
* Account bootstrap funnels six calls through here (via
|
|
1294
|
+
* `AccountService.ensureAccountSpaceHosted`), and each one re-submits
|
|
1295
|
+
* `activateSessionWithHost` with the *primary* session. That session's recap
|
|
1296
|
+
* covers only `default` and `secrets`, so the account space appears in
|
|
1297
|
+
* neither `activated` nor `skipped` and the guard below returns immediately
|
|
1298
|
+
* — the repeat calls cannot change the outcome, they only cost round trips.
|
|
1299
|
+
*
|
|
1300
|
+
* The memo is per sign-in ({@link confirmedHostedSpaceIds} is cleared in
|
|
1301
|
+
* `signIn`) and only records confirmed successes. A wrong skip is
|
|
1302
|
+
* self-revealing: the next write to the space fails immediately and loudly
|
|
1303
|
+
* with `404 Space not found`.
|
|
1304
|
+
*/
|
|
1255
1305
|
private ensureOwnedSpaceHostedById;
|
|
1256
1306
|
/**
|
|
1257
1307
|
* Host one of this user's owned spaces by name (e.g. `"applications"`).
|
|
@@ -1462,6 +1512,14 @@ declare class TinyCloudNode {
|
|
|
1462
1512
|
*/
|
|
1463
1513
|
private requireEncryptionSession;
|
|
1464
1514
|
private createEncryptionCrypto;
|
|
1515
|
+
/**
|
|
1516
|
+
* The node DID for {@link config.host}.
|
|
1517
|
+
*
|
|
1518
|
+
* Sign-in already performs `GET /info` for the protocol-version check, and
|
|
1519
|
+
* that response carries `nodeId`, so reuse it rather than fetching `/info` a
|
|
1520
|
+
* second time. Only a value recorded for this exact host qualifies; older
|
|
1521
|
+
* nodes that omit `nodeId` fall through to the fetch.
|
|
1522
|
+
*/
|
|
1465
1523
|
private fetchNodeId;
|
|
1466
1524
|
private signRawNetworkAuthorization;
|
|
1467
1525
|
private fetchEncryptionNetworkAt;
|
|
@@ -1586,7 +1644,13 @@ declare class TinyCloudNode {
|
|
|
1586
1644
|
get encryption(): IEncryptionService;
|
|
1587
1645
|
getEncryptionNetwork(nameOrNetworkId?: string): Promise<NetworkDescriptor | null>;
|
|
1588
1646
|
createEncryptionNetwork(name?: string): Promise<NetworkDescriptor>;
|
|
1589
|
-
|
|
1647
|
+
/**
|
|
1648
|
+
* Ensure an encryption network exists, creating it if necessary.
|
|
1649
|
+
*
|
|
1650
|
+
* @param nameOrNetworkId - Network name or full `urn:tinycloud:encryption:` id.
|
|
1651
|
+
* @param options - See {@link EnsureEncryptionNetworkOptions}.
|
|
1652
|
+
*/
|
|
1653
|
+
ensureEncryptionNetwork(nameOrNetworkId?: string, options?: EnsureEncryptionNetworkOptions): Promise<NetworkDescriptor>;
|
|
1590
1654
|
/**
|
|
1591
1655
|
* App-facing secrets API backed by the `secrets` space vault.
|
|
1592
1656
|
*/
|
|
@@ -2168,4 +2232,4 @@ declare class WasmKeyProvider implements KeyProvider {
|
|
|
2168
2232
|
*/
|
|
2169
2233
|
declare function createWasmKeyProvider(sessionManager: SessionManagerWithListing): WasmKeyProvider;
|
|
2170
2234
|
|
|
2171
|
-
export { type AuthDelegationArtifact as A, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, FileSessionStorage as F, MemorySessionStorage as M, type NodeEventEmitterStrategy as N, type OwnerDelegationReceipt as O, type PortableDelegation as P, type RestorableSession as R, type SecretPermissionHint as S, TinyCloudNode as T, UnsupportedSessionRestoreError as U, type ValidatedRuntimeDelegation as V, WasmKeyProvider as W, type AuthRequestArtifact as a, type DelegateToResult as b, DelegatedAccess as c, type DelegationAuthority as d, NodeUserAuthorization as e, type NodeUserAuthorizationConfig as f, type RuntimeDelegationActivator as g, type RuntimePermissionGrantOptions as h, type SecretReadInput as i, type SecretReadResult as j, type SignStrategy as k, type TinyCloudNodeConfig as l, type WasmKeyProviderConfig as m, activateValidatedRuntimeDelegation as n, createWasmKeyProvider as o, defaultSignStrategy as p, deserializeDelegation as q, grantAuthRequest as r, serializeDelegation as s };
|
|
2235
|
+
export { type AuthDelegationArtifact as A, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, type EnsureEncryptionNetworkOptions as E, FileSessionStorage as F, MemorySessionStorage as M, type NodeEventEmitterStrategy as N, type OwnerDelegationReceipt as O, type PortableDelegation as P, type RestorableSession as R, type SecretPermissionHint as S, TinyCloudNode as T, UnsupportedSessionRestoreError as U, type ValidatedRuntimeDelegation as V, WasmKeyProvider as W, type AuthRequestArtifact as a, type DelegateToResult as b, DelegatedAccess as c, type DelegationAuthority as d, NodeUserAuthorization as e, type NodeUserAuthorizationConfig as f, type RuntimeDelegationActivator as g, type RuntimePermissionGrantOptions as h, type SecretReadInput as i, type SecretReadResult as j, type SignStrategy as k, type TinyCloudNodeConfig as l, type WasmKeyProviderConfig as m, activateValidatedRuntimeDelegation as n, createWasmKeyProvider as o, defaultSignStrategy as p, deserializeDelegation as q, grantAuthRequest as r, serializeDelegation as s };
|
package/dist/core.cjs
CHANGED
|
@@ -551,6 +551,15 @@ var NodeUserAuthorization = class {
|
|
|
551
551
|
get nodeFeatures() {
|
|
552
552
|
return this._nodeFeatures;
|
|
553
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* The node DID reported by `GET /info` for `host`, if the sign-in (or
|
|
556
|
+
* restore) that populated it targeted that same host. Returns `undefined`
|
|
557
|
+
* for any other host, and for nodes whose `/info` omits `nodeId`, so callers
|
|
558
|
+
* fall back to fetching it themselves rather than using a foreign node's DID.
|
|
559
|
+
*/
|
|
560
|
+
nodeIdForHost(host) {
|
|
561
|
+
return this._nodeInfoIdentity?.host === host ? this._nodeInfoIdentity.nodeId : void 0;
|
|
562
|
+
}
|
|
554
563
|
get lastActivationSkippedSpaceIds() {
|
|
555
564
|
return [...this._lastActivationSkippedSpaceIds];
|
|
556
565
|
}
|
|
@@ -1020,11 +1029,13 @@ var NodeUserAuthorization = class {
|
|
|
1020
1029
|
this._tinyCloudSession = tinyCloudSession;
|
|
1021
1030
|
this._address = address;
|
|
1022
1031
|
this._chainId = chainId;
|
|
1032
|
+
const infoHost = this.primaryTinyCloudHost;
|
|
1023
1033
|
const nodeInfo = await (0, import_sdk_core3.checkNodeInfo)(
|
|
1024
|
-
|
|
1034
|
+
infoHost,
|
|
1025
1035
|
this.wasm.protocolVersion()
|
|
1026
1036
|
);
|
|
1027
1037
|
this._nodeFeatures = nodeInfo.features;
|
|
1038
|
+
this._nodeInfoIdentity = nodeInfo.nodeId ? { host: infoHost, nodeId: nodeInfo.nodeId } : void 0;
|
|
1028
1039
|
for (const ext of this.extensions) {
|
|
1029
1040
|
if (ext.afterSignIn) {
|
|
1030
1041
|
await ext.afterSignIn(clientSession);
|
|
@@ -1190,11 +1201,13 @@ var NodeUserAuthorization = class {
|
|
|
1190
1201
|
this._tinyCloudSession = tinyCloudSession;
|
|
1191
1202
|
this._address = address;
|
|
1192
1203
|
this._chainId = chainId;
|
|
1204
|
+
const infoHost = this.primaryTinyCloudHost;
|
|
1193
1205
|
const nodeInfo = await (0, import_sdk_core3.checkNodeInfo)(
|
|
1194
|
-
|
|
1206
|
+
infoHost,
|
|
1195
1207
|
this.wasm.protocolVersion()
|
|
1196
1208
|
);
|
|
1197
1209
|
this._nodeFeatures = nodeInfo.features;
|
|
1210
|
+
this._nodeInfoIdentity = nodeInfo.nodeId ? { host: infoHost, nodeId: nodeInfo.nodeId } : void 0;
|
|
1198
1211
|
for (const ext of this.extensions) {
|
|
1199
1212
|
if (ext.afterSignIn) {
|
|
1200
1213
|
await ext.afterSignIn(clientSession);
|
|
@@ -2088,6 +2101,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2088
2101
|
this._baseSecrets = /* @__PURE__ */ new Map();
|
|
2089
2102
|
this._secrets = /* @__PURE__ */ new Map();
|
|
2090
2103
|
this.runtimePermissionGrants = [];
|
|
2104
|
+
/**
|
|
2105
|
+
* Owned space ids this sign-in has already confirmed are hosted. Consulted by
|
|
2106
|
+
* {@link ensureOwnedSpaceHostedById}; cleared on every {@link signIn} because
|
|
2107
|
+
* hosting is confirmed against the session that was active at the time.
|
|
2108
|
+
*/
|
|
2109
|
+
this.confirmedHostedSpaceIds = /* @__PURE__ */ new Set();
|
|
2091
2110
|
/**
|
|
2092
2111
|
* True when the last signIn() detected an interactive signer and skipped
|
|
2093
2112
|
* client-side bootstrap. Apps can read this to know whether bootstrap was
|
|
@@ -2484,6 +2503,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2484
2503
|
this._spaceService = void 0;
|
|
2485
2504
|
this._serviceContext = void 0;
|
|
2486
2505
|
this.runtimePermissionGrants = [];
|
|
2506
|
+
this.confirmedHostedSpaceIds.clear();
|
|
2487
2507
|
await this.tc.signIn(options);
|
|
2488
2508
|
this.syncResolvedHostFromAuth();
|
|
2489
2509
|
const oldGraph = this._serviceGraph;
|
|
@@ -2666,14 +2686,18 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2666
2686
|
}
|
|
2667
2687
|
if (step.kind === "seed-applications") {
|
|
2668
2688
|
const registered = await this.account.applications.register(
|
|
2669
|
-
step.manifests.length > 0 ? [...step.manifests] : import_sdk_core8.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST
|
|
2689
|
+
step.manifests.length > 0 ? [...step.manifests] : import_sdk_core8.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
|
|
2690
|
+
// Bootstrap only runs on an account with no registry records, so the
|
|
2691
|
+
// manifest-hash pre-read is definitionally a miss. Skip it; the write
|
|
2692
|
+
// it guards is an INSERT OR REPLACE and is safe to repeat.
|
|
2693
|
+
{ assumeUnregistered: true }
|
|
2670
2694
|
);
|
|
2671
2695
|
if (!registered.ok) {
|
|
2672
2696
|
throw new Error(`Failed to seed bootstrap applications: ${registered.error.message}`);
|
|
2673
2697
|
}
|
|
2674
2698
|
}
|
|
2675
2699
|
if (step.kind === "encryption-network-create") {
|
|
2676
|
-
await this.ensureEncryptionNetwork(step.networkId);
|
|
2700
|
+
await this.ensureEncryptionNetwork(step.networkId, { assumeMissing: true });
|
|
2677
2701
|
}
|
|
2678
2702
|
if (step.kind === "secret-records-schema") {
|
|
2679
2703
|
const db = this.sqlForSpace(step.spaceId).db(step.database);
|
|
@@ -2952,6 +2976,22 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2952
2976
|
await this.ensureEncryptionNetwork(networkId);
|
|
2953
2977
|
}
|
|
2954
2978
|
}
|
|
2979
|
+
/**
|
|
2980
|
+
* Ensure one of this user's owned spaces is hosted, at most once per space
|
|
2981
|
+
* per sign-in.
|
|
2982
|
+
*
|
|
2983
|
+
* Account bootstrap funnels six calls through here (via
|
|
2984
|
+
* `AccountService.ensureAccountSpaceHosted`), and each one re-submits
|
|
2985
|
+
* `activateSessionWithHost` with the *primary* session. That session's recap
|
|
2986
|
+
* covers only `default` and `secrets`, so the account space appears in
|
|
2987
|
+
* neither `activated` nor `skipped` and the guard below returns immediately
|
|
2988
|
+
* — the repeat calls cannot change the outcome, they only cost round trips.
|
|
2989
|
+
*
|
|
2990
|
+
* The memo is per sign-in ({@link confirmedHostedSpaceIds} is cleared in
|
|
2991
|
+
* `signIn`) and only records confirmed successes. A wrong skip is
|
|
2992
|
+
* self-revealing: the next write to the space fails immediately and loudly
|
|
2993
|
+
* with `404 Space not found`.
|
|
2994
|
+
*/
|
|
2955
2995
|
async ensureOwnedSpaceHostedById(spaceId) {
|
|
2956
2996
|
if (!this.auth) {
|
|
2957
2997
|
throw new Error("Owned space hosting requires wallet mode");
|
|
@@ -2960,12 +3000,16 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2960
3000
|
if (!session) {
|
|
2961
3001
|
throw new Error("Owned space hosting requires an active session");
|
|
2962
3002
|
}
|
|
3003
|
+
if (this.confirmedHostedSpaceIds.has(spaceId)) {
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
2963
3006
|
const host = this.hosts[0] ?? this.config.host;
|
|
2964
3007
|
if (!host) {
|
|
2965
3008
|
throw new Error("Owned space hosting requires a TinyCloud host");
|
|
2966
3009
|
}
|
|
2967
3010
|
const activation = await (0, import_sdk_core8.activateSessionWithHost)(host, session.delegationHeader);
|
|
2968
3011
|
if (activation.success && !activation.skipped?.includes(spaceId)) {
|
|
3012
|
+
this.confirmedHostedSpaceIds.add(spaceId);
|
|
2969
3013
|
return;
|
|
2970
3014
|
}
|
|
2971
3015
|
if (!activation.success && activation.status !== 404) {
|
|
@@ -2984,6 +3028,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2984
3028
|
`Failed to activate session after creating owned space ${spaceId}: ${retry.error ?? "space was skipped"}`
|
|
2985
3029
|
);
|
|
2986
3030
|
}
|
|
3031
|
+
this.confirmedHostedSpaceIds.add(spaceId);
|
|
2987
3032
|
}
|
|
2988
3033
|
/**
|
|
2989
3034
|
* Host one of this user's owned spaces by name (e.g. `"applications"`).
|
|
@@ -3306,6 +3351,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3306
3351
|
this.tc = stagedGraph.core;
|
|
3307
3352
|
this._recapOperationsCache = stagedPrimary.cache;
|
|
3308
3353
|
this.runtimePermissionGrants = stagedPrimary.grants;
|
|
3354
|
+
this.confirmedHostedSpaceIds.clear();
|
|
3309
3355
|
if (this.auth) {
|
|
3310
3356
|
this.auth.installRestoredSession(stagedManager, stagedTcSession, [stagedHost]);
|
|
3311
3357
|
this._restoredTcSession = void 0;
|
|
@@ -3888,7 +3934,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3888
3934
|
verifyNodeSignature: (nodeId, message, signature) => (0, import_sdk_core8.verifyDidKeyEd25519Signature)(nodeId, message, signature)
|
|
3889
3935
|
};
|
|
3890
3936
|
}
|
|
3937
|
+
/**
|
|
3938
|
+
* The node DID for {@link config.host}.
|
|
3939
|
+
*
|
|
3940
|
+
* Sign-in already performs `GET /info` for the protocol-version check, and
|
|
3941
|
+
* that response carries `nodeId`, so reuse it rather than fetching `/info` a
|
|
3942
|
+
* second time. Only a value recorded for this exact host qualifies; older
|
|
3943
|
+
* nodes that omit `nodeId` fall through to the fetch.
|
|
3944
|
+
*/
|
|
3891
3945
|
async fetchNodeId() {
|
|
3946
|
+
const cached = this.auth?.nodeIdForHost(this.config.host);
|
|
3947
|
+
if (cached) return cached;
|
|
3892
3948
|
const response = await fetch(`${this.config.host}/info`);
|
|
3893
3949
|
if (!response.ok) {
|
|
3894
3950
|
throw new Error(`Failed to fetch node info: HTTP ${response.status}`);
|
|
@@ -4660,6 +4716,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4660
4716
|
body
|
|
4661
4717
|
)
|
|
4662
4718
|
});
|
|
4719
|
+
if (response.status === 409) {
|
|
4720
|
+
const existing = await this.getEncryptionNetwork(networkId);
|
|
4721
|
+
if (existing) return existing;
|
|
4722
|
+
throw new Error(
|
|
4723
|
+
`Encryption network ${networkId} already exists but could not be read back`
|
|
4724
|
+
);
|
|
4725
|
+
}
|
|
4663
4726
|
if (!response.ok) {
|
|
4664
4727
|
throw new Error(
|
|
4665
4728
|
`Failed to create encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
|
|
@@ -4668,11 +4731,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4668
4731
|
const created = await response.json();
|
|
4669
4732
|
return created.descriptor;
|
|
4670
4733
|
}
|
|
4671
|
-
|
|
4734
|
+
/**
|
|
4735
|
+
* Ensure an encryption network exists, creating it if necessary.
|
|
4736
|
+
*
|
|
4737
|
+
* @param nameOrNetworkId - Network name or full `urn:tinycloud:encryption:` id.
|
|
4738
|
+
* @param options - See {@link EnsureEncryptionNetworkOptions}.
|
|
4739
|
+
*/
|
|
4740
|
+
async ensureEncryptionNetwork(nameOrNetworkId = DEFAULT_ENCRYPTION_NETWORK_NAME, options = {}) {
|
|
4672
4741
|
const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4742
|
+
if (!options.assumeMissing) {
|
|
4743
|
+
const existing = await this.getEncryptionNetwork(networkId);
|
|
4744
|
+
if (existing) {
|
|
4745
|
+
return existing;
|
|
4746
|
+
}
|
|
4676
4747
|
}
|
|
4677
4748
|
const parsed = (0, import_sdk_core8.parseNetworkId)(networkId);
|
|
4678
4749
|
if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
|